p802_15_4mac.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:179k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /********************************************/
  2. /*     NS2 Simulator for IEEE 802.15.4      */
  3. /*           (per P802.15.4/D18)            */
  4. /*------------------------------------------*/
  5. /* by:        Jianliang Zheng               */
  6. /*        (zheng@ee.ccny.cuny.edu)          */
  7. /*              Myung J. Lee                */
  8. /*          (lee@ccny.cuny.edu)             */
  9. /*        ~~~~~~~~~~~~~~~~~~~~~~~~~         */
  10. /*           SAIT-CUNY Joint Lab            */
  11. /********************************************/
  12. // File:  p802_15_4mac.cc
  13. // Mode:  C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t
  14. // $Header: /cvsroot/nsnam/ns-2/wpan/p802_15_4mac.cc,v 1.4 2007/01/30 05:00:52 tom_henderson Exp $
  15. /*
  16.  * Copyright (c) 2003-2004 Samsung Advanced Institute of Technology and
  17.  * The City University of New York. All rights reserved.
  18.  *
  19.  * Redistribution and use in source and binary forms, with or without
  20.  * modification, are permitted provided that the following conditions
  21.  * are met:
  22.  * 1. Redistributions of source code must retain the above copyright
  23.  *    notice, this list of conditions and the following disclaimer.
  24.  * 2. Redistributions in binary form must reproduce the above copyright
  25.  *    notice, this list of conditions and the following disclaimer in the
  26.  *    documentation and/or other materials provided with the distribution.
  27.  * 3. All advertising materials mentioning features or use of this software
  28.  *    must display the following acknowledgement:
  29.  * This product includes software developed by the Joint Lab of Samsung 
  30.  *      Advanced Institute of Technology and The City University of New York.
  31.  * 4. Neither the name of Samsung Advanced Institute of Technology nor of 
  32.  *    The City University of New York may be used to endorse or promote 
  33.  *    products derived from this software without specific prior written 
  34.  *    permission.
  35.  *
  36.  * THIS SOFTWARE IS PROVIDED BY THE JOINT LAB OF SAMSUNG ADVANCED INSTITUTE
  37.  * OF TECHNOLOGY AND THE CITY UNIVERSITY OF NEW YORK ``AS IS'' AND ANY EXPRESS 
  38.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
  39.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 
  40.  * NO EVENT SHALL SAMSUNG ADVANCED INSTITUTE OR THE CITY UNIVERSITY OF NEW YORK 
  41.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  42.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
  43.  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  44.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  45.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
  46.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  47.  */
  48. #include "p802_15_4pkt.h"
  49. #include "p802_15_4mac.h"
  50. #include "p802_15_4const.h"
  51. #include "p802_15_4csmaca.h"
  52. #include "p802_15_4sscs.h"
  53. #include "p802_15_4trace.h"
  54. #include "p802_15_4fail.h"
  55. #include "p802_15_4nam.h"
  56. bool Mac802_15_4::verbose = false;
  57. UINT_8 Mac802_15_4::txOption = 0x00; //0x02=GTS; 0x04=Indirect; 0x00=Direct (only for 802.15.4-unaware upper layer app. packet)
  58. bool Mac802_15_4::ack4data = true;
  59. UINT_8 Mac802_15_4::callBack = 1; //0=no call back; 1=call back for failures; 2=call back for failures and successes
  60. UINT_32 Mac802_15_4::DBG_UID = 0;
  61. static MAC_PIB MPIB =
  62. {
  63. def_macAckWaitDuration, def_macAssociationPermit,
  64. def_macAutoRequest, def_macBattLifeExt,
  65. def_macBattLifeExtPeriods, def_macBeaconPayload,
  66. def_macBeaconPayloadLength, def_macBeaconOrder,
  67. def_macBeaconTxTime, 0/*def_macBSN*/,
  68. def_macCoordExtendedAddress, def_macCoordShortAddress,
  69. 0/*def_macDSN*/, def_macGTSPermit,
  70. def_macMaxCSMABackoffs, def_macMinBE,
  71. def_macPANId, def_macPromiscuousMode,
  72. def_macRxOnWhenIdle, def_macShortAddress,
  73. def_macSuperframeOrder, def_macTransactionPersistenceTime,
  74. def_macACLEntryDescriptorSet, def_macACLEntryDescriptorSetSize,
  75. def_macDefaultSecurity, def_macACLDefaultSecurityMaterialLength,
  76. def_macDefaultSecurityMaterial, def_macDefaultSecuritySuite,
  77. def_macSecurityMode
  78. };
  79. void Mac802_15_4Handler::handle(Event* e)
  80. {
  81. nullEvent.uid_ = 0;
  82. if (type == macTxBcnCmdDataHType)
  83. mac->txBcnCmdDataHandler();
  84. else if (type == macIFSHType)
  85. mac->IFSHandler();
  86. else if (type == macBackoffBoundType)
  87. mac->backoffBoundHandler();
  88. else
  89. assert(0);
  90. }
  91. int hdr_lrwpan::offset_;
  92. static class LRWPANHeaderClass : public PacketHeaderClass
  93. {
  94. public:
  95. LRWPANHeaderClass() : PacketHeaderClass("PacketHeader/LRWPAN",
  96.      sizeof(hdr_lrwpan))
  97. {
  98. bind_offset(&hdr_lrwpan::offset_);
  99. }
  100. } class_hdr_lrwpan;
  101. static class Mac802_15_4Class : public TclClass
  102. {
  103. public:
  104. Mac802_15_4Class() : TclClass("Mac/802_15_4") {}
  105. TclObject* create(int, const char*const*)
  106. {
  107. return (new Mac802_15_4(&MPIB));
  108. }
  109. virtual void bind(void);
  110. virtual int method(int argc, const char*const* argv);
  111. } class_mac802_15_4;
  112. void Mac802_15_4Class::bind(void)
  113. {
  114. TclClass::bind();
  115. add_method("wpanCmd");
  116. add_method("wpanNam");
  117. }
  118. int Mac802_15_4Class::method(int ac, const char*const* av)
  119. {
  120. //Available methods:
  121. // ------------------------------------------------------------------------------------------
  122. // bool Mac802_15_4::verbose; (Tcl command: Mac/802_15_4 wpanCmd verbose [on/off]
  123. // UINT_8 Mac802_15_4::txOption; (Tcl command: Mac/802_15_4 wpanCmd txOption [2/4/0]
  124. // bool Mac802_15_4::ack4data; (Tcl command: Mac/802_15_4 wpanCmd ack4data [on/off]
  125. // UINT_8 Mac802_15_4::callBack; (Tcl command: Mac/802_15_4 wpanCmd callBack [0/1/2]
  126. // link down; (Tcl command: Mac/802_15_4 wpanCmd link-down <src> <dst>
  127. // link up; (Tcl command: Mac/802_15_4 wpanCmd link-up <src> <dst>
  128. // ------------------------------------------------------------------------------------------
  129. // bool Nam802_15_4::Nam_Status; (Tcl command: Mac/802_15_4 wpanNam namStatus [on/off]
  130. // bool Nam802_15_4::emHandling; (Tcl command: Mac/802_15_4 wpanNam emHandling [on/off]
  131. // char *Nam802_15_4::def_PANCoor_clr; (Tcl command: Mac/802_15_4 wpanNam PANCoorClr [clrName]
  132. // char *Nam802_15_4::def_Coor_clr; (Tcl command: Mac/802_15_4 wpanNam CoorClr [clrName]
  133. // char *Nam802_15_4::def_Dev_clr; (Tcl command: Mac/802_15_4 wpanNam DevClr [clrName]
  134. // char *Nam802_15_4::def_ColFlash_clr; (Tcl command: Mac/802_15_4 wpanNam ColFlashClr [clrName]
  135. // char *Nam802_15_4::def_NodeFail_clr; (Tcl command: Mac/802_15_4 wpanNam NodeFailClr [clrName]
  136. // playback rate; (Tcl command: Mac/802_15_4 wpanNam PlaybackRate [step_in_ms]
  137. // flow colors; (Tcl command: Mac/802_15_4 wpanNam FlowClr [-p <packet_type_name>] [-s <src>] [-d <dst>] [-c <clrName>]
  138. // ------------------------------------------------------------------------------------------
  139. Tcl& tcl = Tcl::instance();
  140. int argc = ac - 2;
  141. const char*const* argv = av + 2;
  142. if (strcmp(argv[1], "wpanCmd") == 0)
  143. if (argc == 3)   
  144. {
  145. if (strcmp(argv[2], "verbose") == 0)
  146. {
  147. if (!Mac802_15_4::verbose)
  148. tcl.result("off");
  149. else
  150. tcl.result("on");
  151. return (TCL_OK);
  152. }
  153. else if (strcmp(argv[2], "txOption") == 0)
  154. {
  155. if (Mac802_15_4::txOption == 0x02)
  156. tcl.result("GTS");
  157. else if (Mac802_15_4::txOption == 0x04)
  158. tcl.result("Indirect");
  159. else
  160. tcl.result("Direct");
  161. return (TCL_OK);
  162. }
  163. else if (strcmp(argv[2], "ack4data") == 0)
  164. {
  165. if (!Mac802_15_4::ack4data)
  166. tcl.result("off");
  167. else
  168. tcl.result("on");
  169. return (TCL_OK);
  170. }
  171. else if (strcmp(argv[2], "callBack") == 0)
  172. {
  173. tcl.resultf("%u",Mac802_15_4::callBack);
  174. return (TCL_OK);
  175. }
  176. }
  177. else if (argc == 4)
  178. {
  179. if (strcmp(argv[2], "verbose") == 0)
  180. {
  181. if (strcmp(argv[3], "on") == 0)
  182. Mac802_15_4::verbose = true;
  183. else
  184. Mac802_15_4::verbose = false;
  185. return (TCL_OK);
  186. }
  187. else if (strcmp(argv[2], "txOption") == 0)
  188. {
  189. Mac802_15_4::txOption = atoi(argv[3]);
  190. return (TCL_OK);
  191. }
  192. else if (strcmp(argv[2], "ack4data") == 0)
  193. {
  194. if (strcmp(argv[3], "on") == 0)
  195. Mac802_15_4::ack4data = true;
  196. else
  197. Mac802_15_4::ack4data = false;
  198. return (TCL_OK);
  199. }
  200. else if (strcmp(argv[2], "callBack") == 0)
  201. {
  202. Mac802_15_4::callBack = atoi(argv[3]);
  203. return (TCL_OK);
  204. }
  205. }
  206. else if  (argc == 5)
  207. {
  208. if (strcmp(argv[2], "link-down") == 0)
  209. {
  210. chkAddLFailLink(atoi(argv[3]),atoi(argv[4]));
  211. return (TCL_OK);
  212. }
  213. else if (strcmp(argv[2], "link-up") == 0)
  214. {
  215. updateLFailLink(fl_oper_del,atoi(argv[3]),atoi(argv[4]));
  216. return (TCL_OK);
  217. }
  218. }
  219. if (strcmp(argv[1], "wpanNam") == 0)
  220. if (strcmp(argv[2], "namStatus") == 0)
  221. {
  222. if (argc == 3)
  223. {
  224. if (!Nam802_15_4::Nam_Status)
  225. tcl.result("off");
  226. else
  227. tcl.result("on");
  228. }
  229. else if (argc == 4)
  230. {
  231. if (strcmp(argv[3], "on") == 0)
  232. Nam802_15_4::Nam_Status = true;
  233. else
  234. Nam802_15_4::Nam_Status = false;
  235. }
  236. return (TCL_OK);
  237. }
  238. else if (strcmp(argv[2], "emHandling") == 0)
  239. {
  240. if (argc == 3)
  241. {
  242. if (!Nam802_15_4::emHandling)
  243. tcl.result("off");
  244. else
  245. tcl.result("on");
  246. }
  247. else if (argc == 4)
  248. {
  249. if (strcmp(argv[3], "on") == 0)
  250. Nam802_15_4::emHandling = true;
  251. else
  252. Nam802_15_4::emHandling = false;
  253. }
  254. return (TCL_OK);
  255. }
  256. else if (strcmp(argv[2], "PANCoorClr") == 0)
  257. {
  258. if (argc == 3)
  259. tcl.result(Nam802_15_4::def_PANCoor_clr);
  260. else if (argc >= 4)
  261. {
  262. strncpy(Nam802_15_4::def_PANCoor_clr,argv[3],20);
  263. Nam802_15_4::def_PANCoor_clr[20] = 0;
  264. }
  265. return (TCL_OK);
  266. }
  267. else if (strcmp(argv[2], "CoorClr") == 0)
  268. {
  269. if (argc == 3)
  270. tcl.result(Nam802_15_4::def_Coor_clr);
  271. else if (argc >= 4)
  272. {
  273. strncpy(Nam802_15_4::def_Coor_clr,argv[3],20);
  274. Nam802_15_4::def_Coor_clr[20] = 0;
  275. }
  276. return (TCL_OK);
  277. }
  278. else if (strcmp(argv[2], "DevClr") == 0)
  279. {
  280. if (argc == 3)
  281. tcl.result(Nam802_15_4::def_Dev_clr);
  282. else if (argc >= 4)
  283. {
  284. strncpy(Nam802_15_4::def_Dev_clr,argv[3],20);
  285. Nam802_15_4::def_Dev_clr[20] = 0;
  286. }
  287. return (TCL_OK);
  288. }
  289. else if (strcmp(argv[2], "ColFlashClr") == 0)
  290. {
  291. if (argc == 3)
  292. tcl.result(Nam802_15_4::def_ColFlash_clr);
  293. else if (argc >= 4)
  294. {
  295. strncpy(Nam802_15_4::def_ColFlash_clr,argv[3],20);
  296. Nam802_15_4::def_ColFlash_clr[20] = 0;
  297. }
  298. return (TCL_OK);
  299. }
  300. else if (strcmp(argv[2], "NodeFailClr") == 0)
  301. {
  302. if (argc == 3)
  303. tcl.result(Nam802_15_4::def_NodeFail_clr);
  304. else if (argc >= 4)
  305. {
  306. strncpy(Nam802_15_4::def_NodeFail_clr,argv[3],20);
  307. Nam802_15_4::def_NodeFail_clr[20] = 0;
  308. }
  309. return (TCL_OK);
  310. }
  311. else if (strcmp(argv[2], "PlaybackRate") == 0)
  312. {
  313. if (argc == 3)
  314. tcl.result("??");
  315. else if (argc >= 4)
  316. Nam802_15_4::changePlaybackRate(CURRENT_TIME,argv[3]);
  317. return (TCL_OK);
  318. }
  319. else if (strcmp(argv[2], "FlowClr") == 0)
  320. {
  321. int i,lp,src,dst;
  322. char pName[21],cName[21];
  323. ATTRIBUTELINK *attr;
  324. src = -2;
  325. dst = -2;
  326. strcpy(pName,packet_info.name(PT_NTYPE));
  327. lp = (argc - 3) / 2;
  328. for (i=0;i<lp;i++)
  329. {
  330. if (strcmp(argv[i*2+3],"-p") == 0)
  331. {
  332. strncpy(pName,argv[i*2+4],20);
  333. pName[20] = 0;
  334. }
  335. else if (strcmp(argv[i*2+3],"-s") == 0)
  336. src = atoi(argv[i*2+4]);
  337. else if (strcmp(argv[i*2+3],"-d") == 0)
  338. dst = atoi(argv[i*2+4]);
  339. else if (strcmp(argv[i*2+3],"-c") == 0)
  340. {
  341. strncpy(cName,argv[i*2+4],20);
  342. cName[20] = 0;
  343. }
  344. }
  345. i = chkAddAttrLink(nam_pktName2Type(pName),cName,src,dst);
  346. if (i == 1) //already exist
  347. {
  348. attr = findAttrLink(nam_pktName2Type(pName),src,dst);
  349. if (strcmp(attr->color,cName) != 0) //color changed
  350. {
  351. strncpy(attr->color,cName,20);
  352. attr->color[20] = 0;
  353. Nam802_15_4::flowAttribute(attr->attribute,attr->color);
  354. }
  355. }
  356. else if (i == 0) //added into the link
  357. {
  358. attr = findAttrLink(nam_pktName2Type(pName),src,dst);
  359. Nam802_15_4::flowAttribute(attr->attribute,attr->color);
  360. }
  361. return (TCL_OK);
  362. }
  363. return TclClass::method(ac, av);
  364. }
  365. Mac802_15_4::Mac802_15_4(MAC_PIB *mp) : Mac(),
  366. txCmdDataH(this,macTxBcnCmdDataHType),
  367. IFSH(this,macIFSHType),
  368. backoffBoundH(this,macBackoffBoundType)
  369. {
  370. capability.cap = 0xc1; //alterPANCoor = true
  371. //FFD = true
  372. //mainsPower = false
  373. //recvOnWhenIdle = false
  374. //secuCapable = false
  375. //alloShortAddr = true
  376. capability.parse();
  377. aExtendedAddress = index_;
  378. oneMoreBeacon = false;
  379. isPANCoor = false;
  380. inTransmission = false;
  381. mpib = *mp;
  382. mpib.macBSN = Random::random() % 0x100;
  383. mpib.macDSN = Random::random() % 0x100;
  384. macBeaconOrder2 = 15;
  385. macSuperframeOrder2 = def_macBeaconOrder;
  386. macBeaconOrder3 = 15;
  387. macSuperframeOrder3 = def_macBeaconOrder;
  388. if (mpib.macBeaconOrder == 15) //non-beacon mode
  389. mpib.macRxOnWhenIdle = true; //default is false, but should be true in non-beacon mode
  390. numLostBeacons = 0;
  391. phy = NULL;
  392. txOverT = new macTxOverTimer(this);
  393. assert(txOverT);
  394. txT = new macTxTimer(this);
  395. assert(txT);
  396. extractT = new macExtractTimer(this);
  397. assert(extractT);
  398. assoRspWaitT = new macAssoRspWaitTimer(this);
  399. assert(assoRspWaitT);
  400. dataWaitT = new macDataWaitTimer(this);
  401. assert(dataWaitT);
  402. rxEnableT = new macRxEnableTimer(this);
  403. assert(rxEnableT);
  404. scanT = new macScanTimer(this);
  405. assert(scanT);
  406. bcnTxT = new macBeaconTxTimer(this);
  407. assert(bcnTxT);
  408. bcnRxT = new macBeaconRxTimer(this);
  409. assert(bcnRxT);
  410. bcnSearchT = new macBeaconSearchTimer(this);
  411. assert(bcnSearchT);
  412. wakeupT = new macWakeupTimer(this); // 2.31 change: Wake up timer
  413. assert(wakeupT);  // 2.31 change: Wake up timer
  414. sscs = new SSCS802_15_4(this);
  415. assert(sscs);
  416. nam = new Nam802_15_4((isPANCoor)?Nam802_15_4::def_PANCoor_clr:"black","black",this);
  417. assert(nam);
  418. chkAddMacLink(index_,this);
  419. init();
  420. }
  421. Mac802_15_4::~Mac802_15_4()
  422. {
  423. /*for some reason,this function sometimes is called with <index_> beyond the scope (ns2 bug?)
  424. delete txOverT;
  425. delete txT;
  426. delete extractT;
  427. delete assoRspWaitT;
  428. delete dataWaitT;
  429. delete rxEnableT;
  430. delete scanT;
  431. delete bcnTxT;
  432. delete bcnRxT;
  433. delete bcnSearchT;
  434. delete csmaca;
  435. delete sscs;
  436. delete nam;
  437. */
  438. }
  439. void Mac802_15_4::init(bool reset)
  440. {
  441. secuBeacon = false;
  442. beaconWaiting = false;
  443. txBeacon = 0;
  444. txAck = 0;
  445. txBcnCmd = 0;
  446. txBcnCmd2 = 0;
  447. txData = 0;
  448. rxData = 0;
  449. rxCmd = 0;
  450. if (reset)
  451. {
  452. emptyHListLink(&hlistBLink1,&hlistBLink2);
  453. emptyHListLink(&hlistDLink1,&hlistDLink2);
  454. emptyDeviceLink(&deviceLink1,&deviceLink2);
  455. emptyTransacLink(&transacLink1,&transacLink2);
  456. }
  457. else
  458. {
  459. hlistBLink1 = NULL;
  460. hlistBLink2 = NULL;
  461. hlistDLink1 = NULL;
  462. hlistDLink2 = NULL;
  463. deviceLink1 = NULL;
  464. deviceLink2 = NULL;
  465. transacLink1 = NULL;
  466. transacLink2 = NULL;
  467. }
  468. taskP.init();
  469. }
  470. void Mac802_15_4::PD_DATA_confirm(PHYenum status)
  471. {
  472. inTransmission = false;
  473. if (txOverT->busy())
  474. txOverT->stop();
  475. if (backoffStatus == 1)
  476. backoffStatus = 0;
  477. if (status == p_SUCCESS)
  478. {
  479. dispatch(status,__FUNCTION__);
  480. }
  481. else if (txPkt == txBeacon)
  482. {
  483. beaconWaiting = false;
  484. Packet::free(txBeacon);
  485. txBeacon = 0;
  486. }
  487. else if (txPkt == txAck)
  488. {
  489. Packet::free(txAck);
  490. txAck = 0;
  491. }
  492. 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
  493. {} //nothing to do -- it is the process that terminated the transmisstion to provide a way to resume the transmission
  494. }
  495. void Mac802_15_4::PLME_CCA_confirm(PHYenum status)
  496. {
  497. if (taskP.taskStatus(TP_CCA_csmaca))
  498. {
  499. taskP.taskStatus(TP_CCA_csmaca) = false;
  500. csmaca->CCA_confirm(status);
  501. }
  502. }
  503. void Mac802_15_4::PLME_ED_confirm(PHYenum status,UINT_8 EnergyLevel)
  504. {
  505. energyLevel = EnergyLevel;
  506. dispatch(status,__FUNCTION__);
  507. }
  508. void Mac802_15_4::PLME_GET_confirm(PHYenum status,PPIBAenum PIBAttribute,PHY_PIB *PIBAttributeValue)
  509. {
  510. if (status == p_SUCCESS)
  511. switch(PIBAttribute)
  512. {
  513. case phyCurrentChannel:
  514. tmp_ppib.phyCurrentChannel = PIBAttributeValue->phyCurrentChannel;
  515. break;
  516. case phyChannelsSupported:
  517. tmp_ppib.phyChannelsSupported = PIBAttributeValue->phyChannelsSupported;
  518. break;
  519. case phyTransmitPower:
  520. tmp_ppib.phyTransmitPower = PIBAttributeValue->phyTransmitPower;
  521. break;
  522. case phyCCAMode:
  523. tmp_ppib.phyCCAMode = PIBAttributeValue->phyCCAMode;
  524. break;
  525. default:
  526. break;
  527. }
  528. }
  529. void Mac802_15_4::PLME_SET_TRX_STATE_confirm(PHYenum status)
  530. {
  531. //hdr_lrwpan *wph;
  532. //FrameCtrl frmCtrl;
  533. double delay;
  534. if (status == p_SUCCESS) status = trx_state_req;
  535. if (backoffStatus == 99)
  536. {
  537. if (trx_state_req == p_RX_ON)
  538. {
  539. if (taskP.taskStatus(TP_RX_ON_csmaca))
  540. {
  541. taskP.taskStatus(TP_RX_ON_csmaca) = false;
  542. csmaca->RX_ON_confirm(status);
  543. }
  544. }
  545. }
  546. else
  547. dispatch(status,__FUNCTION__,trx_state_req);
  548. if (status != p_TX_ON) return;
  549. //transmit the packet
  550. if (beaconWaiting)
  551. {
  552. /* to synchronize better, we don't transmit the beacon here
  553. #ifdef DEBUG802_15_4
  554. fprintf(stdout,"[%s::%s][%f](node %d) transmit BEACON to %d: SN = %d, uid = %d, mac_uid = %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macDA(txBeacon),HDR_LRWPAN(txBeacon)->MHR_BDSN,HDR_CMN(txBeacon)->uid(),HDR_LRWPAN(txBeacon)->uid);
  555. #endif
  556. if (!taskP.taskStatus(TP_mlme_start_request)) //not first beacon
  557. assert((!txAck)&&(!txCsmaca)); //all tasks should be done before next beacon
  558. txPkt = txBeacon;
  559. HDR_CMN(txBeacon)->direction() = hdr_cmn::DOWN;
  560. sendDown(txBeacon->refcopy(),this);
  561. */
  562. }
  563. else if (txAck)
  564. {
  565. //although no CSMA-CA required for the transmission of ack., 
  566. //but we still need to locate the backoff period boundary if beacon enabled
  567. //(refer to page 157, line 25-31)
  568. if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15)) //non-beacon enabled
  569. delay = 0.0;
  570. else //beacon enabled
  571. delay  = locateBoundary((p802_15_4macDA(txAck) == mpib.macCoordShortAddress),0.0);
  572. if (delay == 0.0)
  573. backoffBoundHandler();
  574. else
  575. Scheduler::instance().schedule(&backoffBoundH, &(backoffBoundH.nullEvent), delay);
  576. }
  577. else
  578. transmitCmdData();
  579. }
  580. void Mac802_15_4::PLME_SET_confirm(PHYenum status,PPIBAenum PIBAttribute)
  581. {
  582. if ((PIBAttribute == phyCurrentChannel)&&(status == p_SUCCESS))
  583. dispatch(status,__FUNCTION__);
  584. }
  585. void Mac802_15_4::MCPS_DATA_request(UINT_8 SrcAddrMode,UINT_16 SrcPANId,IE3ADDR SrcAddr,
  586.     UINT_8 DstAddrMode,UINT_16 DstPANId,IE3ADDR DstAddr,
  587.     UINT_8 msduLength,Packet *msdu,UINT_8 msduHandle,UINT_8 TxOptions)
  588. {
  589. mcps_data_request(SrcAddrMode,SrcPANId,SrcAddr,DstAddrMode,DstPANId,DstAddr,msduLength,msdu,msduHandle,TxOptions,true);
  590. }
  591. void Mac802_15_4::MCPS_DATA_indication(UINT_8 SrcAddrMode,UINT_16 SrcPANId,IE3ADDR SrcAddr,
  592.        UINT_8 DstAddrMode,UINT_16 DstPANId,IE3ADDR DstAddr,
  593.        UINT_8 msduLength,Packet *msdu,UINT_8 mpduLinkQuality,
  594.        bool SecurityUse,UINT_8 ACLEntry)
  595. {
  596. HDR_CMN(msdu)->num_forwards() += 1;
  597. if (HDR_LRWPAN(msdu)->msduHandle != 0) //from peer SSCS
  598. {
  599. log(msdu->refcopy());
  600. sscs->MCPS_DATA_indication(SrcAddrMode,SrcPANId,SrcAddr,DstAddrMode,DstPANId,DstAddr,msduLength,msdu,mpduLinkQuality,SecurityUse,ACLEntry);
  601. }
  602. else
  603. uptarget_->recv(msdu,(Handler*) 0);
  604. }
  605. void Mac802_15_4::MCPS_PURGE_request(UINT_8 msduHandle)
  606. {
  607. int i;
  608. MACenum t_status;
  609. i = updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,NULL,msduHandle);
  610. t_status = (i == 0)?m_SUCCESS:m_INVALID_HANDLE;
  611. sscs->MCPS_PURGE_confirm(msduHandle,t_status);
  612. }
  613. void Mac802_15_4::MLME_ASSOCIATE_request(UINT_8 LogicalChannel,UINT_8 CoordAddrMode,UINT_16 CoordPANId,IE3ADDR CoordAddress,
  614.  UINT_8 CapabilityInformation,bool SecurityEnable)
  615. {
  616. mlme_associate_request(LogicalChannel,CoordAddrMode,CoordPANId,CoordAddress,CapabilityInformation,SecurityEnable,true);
  617. }
  618. void Mac802_15_4::MLME_ASSOCIATE_response(IE3ADDR DeviceAddress,UINT_16 AssocShortAddress,MACenum status,bool SecurityEnable)
  619. {
  620. mlme_associate_response(DeviceAddress,AssocShortAddress,status,SecurityEnable,true);
  621. }
  622. void Mac802_15_4::MLME_DISASSOCIATE_request(IE3ADDR DeviceAddress,UINT_8 DisassociateReason,bool SecurityEnable)
  623. {
  624. mlme_disassociate_request(DeviceAddress,DisassociateReason,SecurityEnable,true);
  625. }
  626. void Mac802_15_4::MLME_DISASSOCIATE_indication(IE3ADDR DeviceAddress,UINT_8 DisassociateReason,bool SecurityUse,UINT_8 ACLEntry)
  627. {
  628. }
  629. void Mac802_15_4::MLME_GET_request(MPIBAenum PIBAttribute)
  630. {
  631. MACenum t_status;
  632. switch(PIBAttribute)
  633. {
  634. case macAckWaitDuration:
  635. case macAssociationPermit:
  636. case macAutoRequest:
  637. case macBattLifeExt:
  638. case macBattLifeExtPeriods:
  639. case macBeaconPayload:
  640. case macBeaconPayloadLength:
  641. case macBeaconOrder:
  642. case macBeaconTxTime:
  643. case macBSN:
  644. case macCoordExtendedAddress:
  645. case macCoordShortAddress:
  646. case macDSN:
  647. case macGTSPermit:
  648. case macMaxCSMABackoffs:
  649. case macMinBE:
  650. case macPANId:
  651. case macPromiscuousMode:
  652. case macRxOnWhenIdle:
  653. case macShortAddress:
  654. case macSuperframeOrder:
  655. case macTransactionPersistenceTime:
  656. case macACLEntryDescriptorSet:
  657. case macACLEntryDescriptorSetSize:
  658. case macDefaultSecurity:
  659. case macACLDefaultSecurityMaterialLength:
  660. case macDefaultSecurityMaterial:
  661. case macDefaultSecuritySuite:
  662. case macSecurityMode:
  663. t_status = m_SUCCESS;
  664. break;
  665. default:
  666. t_status = m_UNSUPPORTED_ATTRIBUTE;
  667. break;
  668. }
  669. sscs->MLME_GET_confirm(t_status,PIBAttribute,&mpib);
  670. }
  671. void Mac802_15_4::MLME_GTS_request(UINT_8 GTSCharacteristics,bool SecurityEnable)
  672. {
  673. }
  674. void Mac802_15_4::MLME_GTS_confirm(UINT_8 GTSCharacteristics,MACenum status)
  675. {
  676. }
  677. void Mac802_15_4::MLME_GTS_indication(UINT_16 DevAddress,UINT_8 GTSCharacteristics,
  678.       bool SecurityUse, UINT_8 ACLEntry)
  679. {
  680. }
  681. void Mac802_15_4::MLME_ORPHAN_response(IE3ADDR OrphanAddress,UINT_16 ShortAddress,bool AssociatedMember,bool SecurityEnable)
  682. {
  683. mlme_orphan_response(OrphanAddress,ShortAddress,AssociatedMember,SecurityEnable,true);
  684. }
  685. void Mac802_15_4::MLME_RESET_request(bool SetDefaultPIB)
  686. {
  687. mlme_reset_request(SetDefaultPIB,true);
  688. }
  689. void Mac802_15_4::MLME_RX_ENABLE_request(bool DeferPermit,UINT_32 RxOnTime,UINT_32 RxOnDuration)
  690. {
  691. mlme_rx_enable_request(DeferPermit,RxOnTime,RxOnDuration,true);
  692. }
  693. void Mac802_15_4::MLME_SCAN_request(UINT_8 ScanType,UINT_32 ScanChannels,UINT_8 ScanDuration)
  694. {
  695. mlme_scan_request(ScanType,ScanChannels,ScanDuration,true);
  696. }
  697. void Mac802_15_4::MLME_SET_request(MPIBAenum PIBAttribute,MAC_PIB *PIBAttributeValue)
  698. {
  699. PHYenum p_state;
  700. MACenum t_status;
  701. t_status = m_SUCCESS;
  702. switch(PIBAttribute)
  703. {
  704. case macAckWaitDuration:
  705. phy->PLME_GET_request(phyCurrentChannel); //value will be returned in tmp_ppib
  706. if ((tmp_ppib.phyCurrentChannel <= 10)&&(PIBAttributeValue->macAckWaitDuration != 120)
  707.  || (tmp_ppib.phyCurrentChannel > 10)&&(PIBAttributeValue->macAckWaitDuration != 54))
  708. t_status = m_INVALID_PARAMETER;
  709. else
  710. mpib.macAckWaitDuration = PIBAttributeValue->macAckWaitDuration;
  711. break;
  712. case macAssociationPermit:
  713. mpib.macAssociationPermit = PIBAttributeValue->macAssociationPermit;
  714. break;
  715. case macAutoRequest:
  716. mpib.macAutoRequest = PIBAttributeValue->macAutoRequest;
  717. break;
  718. case macBattLifeExt:
  719. mpib.macBattLifeExt = PIBAttributeValue->macBattLifeExt;
  720. break;
  721. case macBattLifeExtPeriods:
  722. phy->PLME_GET_request(phyCurrentChannel); //value will be returned in tmp_ppib
  723. if ((tmp_ppib.phyCurrentChannel <= 10)&&(PIBAttributeValue->macBattLifeExtPeriods != 8)
  724.  || (tmp_ppib.phyCurrentChannel > 10)&&(PIBAttributeValue->macBattLifeExtPeriods != 6))
  725. t_status = m_INVALID_PARAMETER;
  726. else
  727. mpib.macBattLifeExtPeriods = PIBAttributeValue->macBattLifeExtPeriods;
  728. break;
  729. case macBeaconPayload:
  730. //<macBeaconPayloadLength> should be set first
  731. memcpy(mpib.macBeaconPayload,PIBAttributeValue->macBeaconPayload,mpib.macBeaconPayloadLength);
  732. break;
  733. case macBeaconPayloadLength:
  734. if (PIBAttributeValue->macBeaconPayloadLength > aMaxBeaconPayloadLength)
  735. t_status = m_INVALID_PARAMETER;
  736. else
  737. mpib.macBeaconPayloadLength = PIBAttributeValue->macBeaconPayloadLength;
  738. break;
  739. case macBeaconOrder:
  740. if (PIBAttributeValue->macBeaconOrder > 15)
  741. t_status = m_INVALID_PARAMETER;
  742. else
  743. mpib.macBeaconOrder = PIBAttributeValue->macBeaconOrder;
  744. break;
  745. case macBeaconTxTime:
  746. mpib.macBeaconTxTime = PIBAttributeValue->macBeaconTxTime;
  747. break;
  748. case macBSN:
  749. mpib.macBSN = PIBAttributeValue->macBSN;
  750. break;
  751. case macCoordExtendedAddress:
  752. mpib.macCoordExtendedAddress = PIBAttributeValue->macCoordExtendedAddress;
  753. break;
  754. case macCoordShortAddress:
  755. mpib.macCoordShortAddress = PIBAttributeValue->macCoordShortAddress;
  756. break;
  757. case macDSN:
  758. mpib.macDSN = PIBAttributeValue->macDSN;
  759. break;
  760. case macGTSPermit:
  761. mpib.macGTSPermit = PIBAttributeValue->macGTSPermit;
  762. break;
  763. case macMaxCSMABackoffs:
  764. if (PIBAttributeValue->macMaxCSMABackoffs > 5)
  765. t_status = m_INVALID_PARAMETER;
  766. else
  767. mpib.macMaxCSMABackoffs = PIBAttributeValue->macMaxCSMABackoffs;
  768. break;
  769. case macMinBE:
  770. if (PIBAttributeValue->macMinBE > 3)
  771. t_status = m_INVALID_PARAMETER;
  772. else
  773. mpib.macMinBE = PIBAttributeValue->macMinBE;
  774. break;
  775. case macPANId:
  776. mpib.macPANId = PIBAttributeValue->macPANId;
  777. break;
  778. case macPromiscuousMode:
  779. mpib.macPromiscuousMode = PIBAttributeValue->macPromiscuousMode;
  780. //some other operations (refer to sec. 7.5.6.6)
  781. mpib.macRxOnWhenIdle = PIBAttributeValue->macPromiscuousMode;
  782. p_state = mpib.macRxOnWhenIdle?p_RX_ON:p_TRX_OFF;
  783. phy->PLME_SET_TRX_STATE_request(p_state);
  784. break;
  785. case macRxOnWhenIdle:
  786. mpib.macRxOnWhenIdle = PIBAttributeValue->macRxOnWhenIdle;
  787. break;
  788. case macShortAddress:
  789. mpib.macShortAddress = PIBAttributeValue->macShortAddress;
  790. break;
  791. case macSuperframeOrder:
  792. if (PIBAttributeValue->macSuperframeOrder > 15)
  793. t_status = m_INVALID_PARAMETER;
  794. else
  795. mpib.macSuperframeOrder = PIBAttributeValue->macSuperframeOrder;
  796. break;
  797. case macTransactionPersistenceTime:
  798. mpib.macTransactionPersistenceTime = PIBAttributeValue->macTransactionPersistenceTime;
  799. break;
  800. case macACLEntryDescriptorSet:
  801. case macACLEntryDescriptorSetSize:
  802. case macDefaultSecurity:
  803. case macACLDefaultSecurityMaterialLength:
  804. case macDefaultSecurityMaterial:
  805. case macDefaultSecuritySuite:
  806. case macSecurityMode:
  807. break; //currently security ignored in simulation
  808. default:
  809. t_status = m_UNSUPPORTED_ATTRIBUTE;
  810. break;
  811. }
  812. sscs->MLME_SET_confirm(t_status,PIBAttribute);
  813. }
  814. void Mac802_15_4::MLME_START_request(UINT_16 PANId,UINT_8 LogicalChannel,UINT_8 BeaconOrder,
  815.      UINT_8 SuperframeOrder,bool PANCoordinator,bool BatteryLifeExtension,
  816.      bool CoordRealignment,bool SecurityEnable)
  817. {
  818. mlme_start_request(PANId,LogicalChannel,BeaconOrder,SuperframeOrder,PANCoordinator,BatteryLifeExtension,CoordRealignment,SecurityEnable,true);
  819. }
  820. void Mac802_15_4::MLME_SYNC_request(UINT_8 LogicalChannel, bool TrackBeacon)
  821. {
  822. mlme_sync_request(LogicalChannel,TrackBeacon,true);
  823. }
  824. void Mac802_15_4::MLME_POLL_request(UINT_8 CoordAddrMode,UINT_16 CoordPANId,IE3ADDR CoordAddress,bool SecurityEnable)
  825. {
  826. mlme_poll_request(CoordAddrMode,CoordPANId,CoordAddress,SecurityEnable,false,true);
  827. }
  828. inline int Mac802_15_4::hdr_dst(char* hdr, int dst)
  829. {
  830. return p802_15_4hdr_dst(hdr,dst);
  831. }
  832. inline int Mac802_15_4::hdr_src(char* hdr, int src)
  833. {
  834. return p802_15_4hdr_src(hdr,src);
  835. }
  836. inline int Mac802_15_4::hdr_type(char* hdr, UINT_16 type)
  837. {
  838. return p802_15_4hdr_type(hdr,type);
  839. }
  840. void Mac802_15_4::recv(Packet *p, Handler *h)
  841. {
  842. hdr_lrwpan* wph = HDR_LRWPAN(p);
  843. hdr_cmn *ch = HDR_CMN(p);
  844. bool noAck;
  845. int i;
  846. UINT_8 txop;
  847. FrameCtrl frmCtrl;
  848. SuperframeSpec t_sfSpec;
  849. if (!Nam802_15_4::emStatus)
  850. Nam802_15_4::emStatus = (netif_->node()->energy_model()?true:false); //is there a better place to do this?
  851. if(ch->direction() == hdr_cmn::DOWN) //outgoing packet
  852. {
  853. #ifdef DEBUG802_15_4
  854. fprintf(stdout,"[%s::%s][%f](node %d) outgoing pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = ??, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),ch->size());
  855. #endif
  856. //-- Notes for power-saving:
  857. //   It turns out to be very difficult to apply sleeping model in 802.15.4.
  858. //   First, a node shouldn't go to sleep if peer2peer transmission mode is
  859. //   used. Non-peer2peer means that a node only communicates with its parent 
  860. //   and/or children, which requests that pure tree routing be used.
  861. //   Second, even pure tree routing is used, a node can only go to sleep
  862. //   if it satisfies both the sleeping condition as a parent (to its children)
  863. //   and that as a child (to its parent) in a multi-hop environment. To 
  864. //   satisfy both conditions requires efficient scheduling scheme.
  865. //   Since ns2, by default, treats the power consumption in idle mode same 
  866. //   as that in sleeping mode, it makes no difference at this moment whether
  867. //   we set sleeping mode or not.
  868. //wake up the node if it is in sleep mode (only for legacy applications)
  869. EnergyModel *em = netif_->node()->energy_model();
  870. if (em)
  871. {
  872. if (em->energy() <= 0)
  873. {
  874. drop(p,"ENE");
  875. return;
  876. }
  877. #ifdef SHUTDOWN
  878. phy->wakeupNode(1);
  879. #endif
  880. }
  881. /* SSCS should call MCPS_DATA_request() directly
  882. if (from SSCS)
  883. {
  884. MCPS_DATA_request(wph->SrcAddrMode,wph->SrcPANId,wph->SrcAddr,
  885.   wph->DstAddrMode,wph->DstPANId,wph->DstAddr,
  886.   ch->size(),p,wph->msduHandle,wph->TxOptions);
  887. }
  888. else //802.15.4-unaware upper layer app. packet
  889. */
  890. {
  891. callback_ = h;
  892. if (p802_15_4macDA(p) == (nsaddr_t)MAC_BROADCAST)
  893. txop = 0;
  894. else
  895. {
  896. if (Mac802_15_4::ack4data)
  897. txop = TxOp_Acked;
  898. else
  899. txop = 0;
  900. txop |= Mac802_15_4::txOption;
  901. }
  902. wph->msduHandle = 0;
  903. MCPS_DATA_request(0,0,0,defFrmCtrl_AddrMode16,mpib.macPANId,p802_15_4macDA(p),ch->size(),p,0,txop); //direct transmission w/o security
  904. }
  905. return;
  906. }
  907. else //incoming packet
  908. {
  909. #ifdef DEBUG802_15_4
  910. fprintf(stdout,"[%s::%s][%f](node %d) incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  911. #endif
  912. resetCounter(p802_15_4macSA(p));
  913. //if during ED scan, discard all frames received over the PHY layer data service (sec. 7.5.2.1.1)
  914. //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)
  915. //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)
  916. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  917. frmCtrl.parse();
  918. if (taskP.taskStatus(TP_mlme_scan_request))
  919. if (taskP.mlme_scan_request_ScanType == 0x00) //ED scan
  920. {
  921. #ifdef DEBUG802_15_4
  922. fprintf(stdout,"[D][ED][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  923. #endif
  924. drop(p,"ED");
  925. return;
  926. }
  927. else if (((taskP.mlme_scan_request_ScanType == 0x01) //Active scan
  928.         ||(taskP.mlme_scan_request_ScanType == 0x02)) //Passive scan
  929.      && (frmCtrl.frmType != defFrmCtrl_Type_Beacon))
  930. {
  931. #ifdef DEBUG802_15_4
  932. fprintf(stdout,"[D][APS][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  933. #endif
  934. drop(p,"APS");
  935. return;
  936. }
  937. else if ((taskP.mlme_scan_request_ScanType == 0x03) //Orphan scan
  938.      && ((frmCtrl.frmType != defFrmCtrl_Type_MacCmd)||(wph->MSDU_CmdType != 0x08)))
  939. {
  940. #ifdef DEBUG802_15_4
  941. fprintf(stdout,"[D][OPH][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  942. #endif
  943. drop(p,"OPH");
  944. return;
  945. }
  946. //drop the packet if corrupted
  947. if (ch->error())
  948. {
  949. #ifdef DEBUG802_15_4
  950. fprintf(stdout,"[D][ERR][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  951. #endif
  952. drop(p,"ERR");
  953. return;
  954. }
  955. //drop the packet if the link quality is too bad (basically, collisions)
  956. if ((wph->rxTotPower-p->txinfo_.RxPr) > 0.0)
  957. if (p->txinfo_.RxPr/(wph->rxTotPower-p->txinfo_.RxPr) < p->txinfo_.CPThresh)
  958. {
  959. #ifdef DEBUG802_15_4
  960. fprintf(stdout,"[D][LQI][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  961. #endif
  962. if (!wph->colFlag)
  963. nam->flashNodeColor(CURRENT_TIME);
  964. drop(p,"LQI");
  965. return;
  966. }
  967. if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
  968. {
  969. t_sfSpec.SuperSpec = wph->MSDU_SuperSpec;
  970. t_sfSpec.parse();
  971. if (t_sfSpec.BO != 15)
  972. {
  973. //update superframe specification
  974. sfSpec3 = t_sfSpec;
  975. //calculate the time when we received the first bit of the beacon
  976. macBcnOtherRxTime = (CURRENT_TIME - phy->trxTime(p)) * phy->getRate('s');
  977. //update beacon order and superframe order
  978. macBeaconOrder3 = sfSpec3.BO;
  979. macSuperframeOrder3 = sfSpec3.SO;
  980. }
  981. }
  982. //---perform filtering (refer to sec. 7.5.6.2)---
  983. //drop the packet if FCS is not correct (ignored in simulation)
  984. if (ch->ptype() == PT_MAC) //perform further filtering only if it is an 802.15.4 packet
  985. if (!mpib.macPromiscuousMode) //perform further filtering only if the PAN is currently not in promiscuous mode
  986. {
  987. //check packet type
  988. if ((frmCtrl.frmType != defFrmCtrl_Type_Beacon)
  989.   &&(frmCtrl.frmType != defFrmCtrl_Type_Data)
  990.   &&(frmCtrl.frmType != defFrmCtrl_Type_Ack)
  991.   &&(frmCtrl.frmType != defFrmCtrl_Type_MacCmd))
  992. {
  993. #ifdef DEBUG802_15_4
  994. fprintf(stdout,"[D][TYPE][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  995. #endif
  996. drop(p,"TYPE");
  997. return;
  998. }
  999. //check source PAN ID for beacon frame
  1000. if ((frmCtrl.frmType == defFrmCtrl_Type_Beacon)
  1001.   &&(mpib.macPANId != 0xffff)
  1002.   &&(wph->MHR_SrcAddrInfo.panID != mpib.macPANId))
  1003. {
  1004. #ifdef DEBUG802_15_4
  1005. fprintf(stdout,"[D][PAN][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1006. #endif
  1007. drop(p,"PAN");
  1008. return;
  1009. }
  1010. //check dest. PAN ID if it is included
  1011. if ((frmCtrl.dstAddrMode == defFrmCtrl_AddrMode16)
  1012.   ||(frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64))
  1013. if ((wph->MHR_DstAddrInfo.panID != 0xffff)
  1014.   &&(wph->MHR_DstAddrInfo.panID != mpib.macPANId))
  1015. {
  1016. #ifdef DEBUG802_15_4
  1017. fprintf(stdout,"[D][PAN][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1018. #endif
  1019. drop(p,"PAN");
  1020. return;
  1021. }
  1022. //check dest. address if it is included
  1023. if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode16)
  1024. {
  1025. if ((wph->MHR_DstAddrInfo.addr_16 != 0xffff)
  1026.  && (wph->MHR_DstAddrInfo.addr_16 != mpib.macShortAddress))
  1027. {
  1028. #ifdef DEBUG802_15_4
  1029. fprintf(stdout,"[D][ADR][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1030. #endif
  1031. drop(p,"ADR");
  1032. return;
  1033. }
  1034. }
  1035. else if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64)
  1036. {
  1037. if (wph->MHR_DstAddrInfo.addr_64 != aExtendedAddress)
  1038. {
  1039. #ifdef DEBUG802_15_4
  1040. fprintf(stdout,"[D][ADR][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1041. #endif
  1042. drop(p,"ADR");
  1043. return;
  1044. }
  1045. }
  1046. //check for Data/MacCmd frame only w/ source address
  1047. if ((frmCtrl.frmType == defFrmCtrl_Type_Data)
  1048.   ||(frmCtrl.frmType == defFrmCtrl_Type_MacCmd))
  1049. if (frmCtrl.dstAddrMode == defFrmCtrl_AddrModeNone)
  1050. {
  1051. if (((!capability.FFD)||(numberDeviceLink(&deviceLink1) == 0)) //I am not a coordinator
  1052.   ||(wph->MHR_SrcAddrInfo.panID != mpib.macPANId))
  1053. {
  1054. #ifdef DEBUG802_15_4
  1055. fprintf(stdout,"[D][PAN][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1056. #endif
  1057. drop(p,"PAN");
  1058. return;
  1059. }
  1060. }
  1061. //we need to add one more filter for supporting multi-hop beacon enabled mode (not in the draft)
  1062. if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
  1063. if (wph->MHR_DstAddrInfo.panID != 0xffff)
  1064. if ((mpib.macCoordExtendedAddress != wph->MHR_SrcAddrInfo.addr_64) //ok even for short address (in simulation)
  1065. &&  (mpib.macCoordExtendedAddress != def_macCoordExtendedAddress))
  1066. {
  1067. #ifdef DEBUG802_15_4
  1068. fprintf(stdout,"[D][COO][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1069. #endif
  1070. drop(p,"COO");
  1071. return;
  1072. }
  1073. } //---filtering done---
  1074. //perform security task if required (ignored in simulation)
  1075. //send an acknowledgement if needed (no matter this is a duplicated packet or not)
  1076. if ((frmCtrl.frmType == defFrmCtrl_Type_Data)
  1077.   ||(frmCtrl.frmType == defFrmCtrl_Type_MacCmd))
  1078. if (frmCtrl.ackReq) //acknowledgement required
  1079. {
  1080. //association request command will be ignored under following cases
  1081. if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
  1082.  && (wph->MSDU_CmdType == 0x01))
  1083. if ((!capability.FFD) //not an FFD
  1084.  || (mpib.macShortAddress == 0xffff) //not yet joined any PAN
  1085.  || (!macAssociationPermit)) //association not permitted
  1086. {
  1087. Packet::free(p);
  1088. return;
  1089. }
  1090. noAck = false;
  1091. if (frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
  1092. if ((rxCmd)||(txBcnCmd))
  1093. noAck = true;
  1094. if (!noAck)
  1095. {
  1096. constructACK(p);
  1097. //stop CSMA-CA if it is pending (it will be restored after the transmission of ACK)
  1098. if (backoffStatus == 99)
  1099. {
  1100. backoffStatus = 0;
  1101. csmaca->cancel();
  1102. }
  1103. plme_set_trx_state_request(p_TX_ON);
  1104. }
  1105. }
  1106. else
  1107. resetTRX();
  1108. if (frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
  1109. if ((rxCmd)||(txBcnCmd))
  1110. {
  1111. #ifdef DEBUG802_15_4
  1112. {
  1113. fprintf(stdout,"[D][BSY][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1114. if (rxCmd)
  1115. fprintf(stdout,"trxCmd pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",wpan_pName(rxCmd),p802_15_4macSA(rxCmd),p802_15_4macDA(rxCmd),HDR_CMN(rxCmd)->uid(),HDR_LRWPAN(rxCmd)->uid,HDR_CMN(rxCmd)->size());
  1116. if (txBcnCmd)
  1117. fprintf(stdout,"ttxBcnCmd pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",wpan_pName(txBcnCmd),p802_15_4macSA(txBcnCmd),p802_15_4macDA(txBcnCmd),HDR_CMN(txBcnCmd)->uid(),HDR_LRWPAN(txBcnCmd)->uid,HDR_CMN(txBcnCmd)->size());
  1118. }
  1119. #endif
  1120. drop(p,"BSY");
  1121. return;
  1122. }
  1123. if (frmCtrl.frmType == defFrmCtrl_Type_Data)
  1124. if (rxData)
  1125. {
  1126. #ifdef DEBUG802_15_4
  1127. fprintf(stdout,"[D][BSY][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1128. #endif
  1129. drop(p,"BSY");
  1130. return;
  1131. }
  1132. //check duplication -- must be performed AFTER all drop's
  1133. if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
  1134. i = chkAddUpdHListLink(&hlistBLink1,&hlistBLink2,p802_15_4macSA(p),wph->MHR_BDSN);
  1135. else if (frmCtrl.frmType != defFrmCtrl_Type_Ack)
  1136. i = chkAddUpdHListLink(&hlistDLink1,&hlistDLink2,p802_15_4macSA(p),wph->MHR_BDSN);
  1137. else //Acknowledgement
  1138. {
  1139. assert(txPkt);
  1140. if (wph->MHR_BDSN != HDR_LRWPAN(txPkt)->MHR_BDSN)
  1141. i = 2;
  1142. else i = 0;
  1143. }
  1144. if (i == 2)
  1145. {
  1146. #ifdef DEBUG802_15_4
  1147. fprintf(stdout,"[D][DUP][%s::%s][%f](node %d) dropping duplicated packet: type = %s, from = %d, uid = %d, mac_uid = %ld, size = %d, SN = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),ch->uid(),wph->uid,ch->size(),wph->MHR_BDSN);
  1148. #endif
  1149. drop(p,"DUP");
  1150. return;
  1151. }
  1152. //handle the beacon packet
  1153. if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
  1154. recvBeacon(p);
  1155. //handle the ack. packet
  1156. else if (frmCtrl.frmType == defFrmCtrl_Type_Ack)
  1157. recvAck(p);
  1158. //handle the command packet
  1159. else if (frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
  1160. recvCommand(p);
  1161. //handle the data packet
  1162. else if (frmCtrl.frmType == defFrmCtrl_Type_Data)
  1163. {
  1164. recvData(p);
  1165. }
  1166. }
  1167. }
  1168. void Mac802_15_4::recvBeacon(Packet *p)
  1169. {
  1170. hdr_lrwpan* wph = HDR_LRWPAN(p);
  1171. FrameCtrl frmCtrl;
  1172. PendAddrSpec pendSpec;
  1173. bool pending;
  1174. double txtime;
  1175. UINT_8 ifs;
  1176. int i;
  1177. //update superframe specification
  1178. sfSpec2.SuperSpec = wph->MSDU_SuperSpec;
  1179. sfSpec2.parse();
  1180. #ifdef DEBUG802_15_4
  1181. hdr_cmn* ch = HDR_CMN(p);
  1182. fprintf(stdout,"[%s::%s][%f](node %d) M_BEACON [BO:%d][SO:%d] received: from = %d, uid = %d, mac_uid = %ld, size = %d, SN = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,sfSpec2.BO,sfSpec2.SO,p802_15_4macSA(p),ch->uid(),wph->uid,ch->size(),wph->MHR_BDSN);
  1183. #endif
  1184. //calculate the time when we received the first bit of the beacon
  1185. txtime = phy->trxTime(p);
  1186. /* Linux floating number compatibility
  1187. macBcnRxTime = (CURRENT_TIME - txtime) * phy->getRate('s');
  1188. */
  1189. {
  1190. double tmpf;
  1191. tmpf = CURRENT_TIME - txtime;
  1192. macBcnRxTime = tmpf * phy->getRate('s');
  1193. }
  1194. //calculate <beaconPeriods2>
  1195. if (HDR_CMN(p)->size() <= aMaxSIFSFrameSize)
  1196. ifs = aMinSIFSPeriod;
  1197. else
  1198. ifs = aMinLIFSPeriod;
  1199. /* Linux floating number compatibility
  1200. beaconPeriods2 = (UINT_8)((txtime * phy->getRate('s') + ifs) / aUnitBackoffPeriod);
  1201. */
  1202. double tmpf;
  1203. tmpf = txtime * phy->getRate('s');
  1204. tmpf += ifs;
  1205. beaconPeriods2 = (UINT_8)(tmpf / aUnitBackoffPeriod);
  1206. /* Linux floating number compatibility
  1207. if (fmod((txtime * phy->getRate('s')+ ifs) ,aUnitBackoffPeriod) > 0.0)
  1208. */
  1209. if (fmod(tmpf ,aUnitBackoffPeriod) > 0.0)
  1210. beaconPeriods2++;
  1211. //update PAN descriptor
  1212. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  1213. frmCtrl.parse();
  1214. panDes2.CoordAddrMode = frmCtrl.srcAddrMode;
  1215. panDes2.CoordPANId = wph->MHR_SrcAddrInfo.panID;
  1216. panDes2.CoordAddress_64 = wph->MHR_SrcAddrInfo.addr_64; //ok even it is a 16-bit address
  1217. panDes2.LogicalChannel = wph->phyCurrentChannel;
  1218. panDes2.SuperframeSpec = wph->MSDU_SuperSpec;
  1219. gtsSpec2.fields = wph->MSDU_GTSFields;
  1220. gtsSpec2.parse();
  1221. panDes2.GTSPermit = gtsSpec2.permit;
  1222. panDes2.LinkQuality = wph->ppduLinkQuality;
  1223. panDes2.TimeStamp = (UINT_32)macBcnRxTime;
  1224. panDes2.SecurityUse = wph->SecurityUse;
  1225. panDes2.ACLEntry = wph->ACLEntry;
  1226. panDes2.SecurityFailure = false; //ignored in simulation
  1227. panDes2.clusTreeDepth = wph->clusTreeDepth;
  1228. //handle active and passive channel scans
  1229. if ((taskP.taskStatus(TP_mlme_scan_request))
  1230.  || (taskP.taskStatus(TP_mlme_rx_enable_request)))
  1231. {
  1232. rxBeacon = p;
  1233. dispatch(p_SUCCESS,__FUNCTION__);
  1234. }
  1235. if ((mpib.macPANId == 0xffff)
  1236. || (mpib.macPANId != panDes2.CoordPANId)
  1237. || (taskP.taskStatus(TP_mlme_associate_request)))
  1238. {
  1239. Packet::free(p);
  1240. return;
  1241. }
  1242. numLostBeacons = 0;
  1243. nam->flashNodeMark(CURRENT_TIME);
  1244. macBeaconOrder2 = sfSpec2.BO;
  1245. macSuperframeOrder2 = sfSpec2.SO;
  1246. //populate <macCoordShortAddress> if needed
  1247. if (mpib.macCoordShortAddress == def_macCoordShortAddress)
  1248. if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode16)
  1249. mpib.macCoordShortAddress = wph->MHR_SrcAddrInfo.addr_16;
  1250. dispatch(p_SUCCESS,__FUNCTION__);
  1251. //resume extraction timer if needed
  1252. extractT->resume();
  1253. //CSMA-CA may be waiting for the new beacon
  1254. if (wph->MHR_SrcAddrInfo.panID == mpib.macPANId)
  1255. if (backoffStatus == 99)
  1256. csmaca->newBeacon('r');
  1257. //check if need to notify the upper layer
  1258. if ((!mpib.macAutoRequest)||(wph->MSDU_PayloadLen > 0))
  1259. sscs->MLME_BEACON_NOTIFY_indication(wph->MHR_BDSN,&panDes2,wph->MSDU_PendAddrFields.spec,wph->MSDU_PendAddrFields.addrList,wph->MSDU_PayloadLen,wph->MSDU_Payload);
  1260. if (mpib.macAutoRequest)
  1261. {
  1262. //handle the pending packet
  1263. pendSpec.fields = wph->MSDU_PendAddrFields;
  1264. pendSpec.parse();
  1265. pending = false;
  1266. for (i=0;i<pendSpec.numShortAddr;i++)
  1267. {
  1268. if (pendSpec.fields.addrList[i] == mpib.macShortAddress)
  1269. {
  1270. pending = true;
  1271. break;
  1272. }
  1273. }
  1274. if (!pending)
  1275. for (i=0;i<pendSpec.numExtendedAddr;i++)
  1276. {
  1277. if (pendSpec.fields.addrList[pendSpec.numShortAddr + i] == aExtendedAddress)
  1278. {
  1279. pending = true;
  1280. break;
  1281. }
  1282. }
  1283. if (pending)
  1284. {
  1285. //frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  1286. //frmCtrl.parse();
  1287. mlme_poll_request(frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.panID,wph->MHR_SrcAddrInfo.addr_64,capability.secuCapable,true,true);
  1288. }
  1289. else
  1290. {
  1291. #ifdef SHUTDOWN
  1292. if ((backoffStatus!=99) && ((!capability.FFD)||(numberDeviceLink(&deviceLink1) == 0)) && (NOW>phy->T_sleep_)) { //2.31 change: added this if statement to put the node to sleep after beacon reception if the node is not attempting to tx a pkt
  1293. phy->putNodeToSleep();
  1294. }
  1295. #endif
  1296. }
  1297. log(p);
  1298. }
  1299. }
  1300. void Mac802_15_4::recvAck(Packet *p)
  1301. {
  1302. hdr_lrwpan *wph;
  1303. hdr_cmn *ch;
  1304. FrameCtrl frmCtrl;
  1305. wph = HDR_LRWPAN(p);
  1306. ch = HDR_CMN(p);
  1307. #ifdef DEBUG802_15_4
  1308. fprintf(stdout,"[%s::%s][%f](node %d) M_ACK received: from = %d, SN = %d, uid = %d, mac_uid = %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macSA(p),wph->MHR_BDSN,ch->uid(),wph->uid);
  1309. #endif
  1310. if ((!txBcnCmd)&&(!txBcnCmd2)&&(!txData))
  1311. {
  1312. Packet::free(p);
  1313. return;
  1314. }
  1315. //check the sequence number in the ack. to see if it matches that in the <txPkt>
  1316. if (wph->MHR_BDSN != HDR_LRWPAN(txPkt)->MHR_BDSN)
  1317. {
  1318. Packet::free(p);
  1319. return;
  1320. }
  1321. if (txT->busy())
  1322. txT->stop();
  1323. else
  1324. {
  1325. #ifdef DEBUG802_15_4
  1326. fprintf(stdout,"[%s::%s][%f](node %d) LATE ACK received: from = %d, SN = %d, uid = %d, mac_uid = %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macSA(p),wph->MHR_BDSN,ch->uid(),wph->uid);
  1327. #endif
  1328. //only handle late ack. for data packet
  1329. if (txPkt != txData)
  1330. {
  1331. Packet::free(p);
  1332. return;
  1333. }
  1334. if (backoffStatus == 99)
  1335. {
  1336. backoffStatus = 0;
  1337. csmaca->cancel();
  1338. }
  1339. }
  1340. //set pending flag for data polling
  1341. if (txPkt == txBcnCmd2)
  1342. if ((taskP.taskStatus(TP_mlme_poll_request))
  1343.  && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),__FUNCTION__) == 0))
  1344. {
  1345. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  1346. frmCtrl.parse();
  1347. taskP.mlme_poll_request_pending = frmCtrl.frmPending;
  1348. }
  1349. dispatch(p_SUCCESS,__FUNCTION__);
  1350. log(p);
  1351. }
  1352. void Mac802_15_4::recvCommand(Packet *p)
  1353. {
  1354. hdr_lrwpan* wph;
  1355. FrameCtrl frmCtrl;
  1356. bool ackReq;
  1357. #ifdef DEBUG802_15_4
  1358. wph = HDR_LRWPAN(p);
  1359. hdr_cmn* ch = HDR_CMN(p);
  1360. fprintf(stdout,"[%s::%s][%f](node %d) %s received: from = %d, uid = %d, mac_uid = %ld, size = %d, SN = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),ch->uid(),wph->uid,ch->size(),wph->MHR_BDSN);
  1361. #endif
  1362. ackReq = false;
  1363. switch(HDR_LRWPAN(p)->MSDU_CmdType)
  1364. {
  1365. case 0x01: //Association request
  1366. //recv() is in charge of sending ack.
  1367. //MLME-ASSOCIATE.indication() will be passed to upper layer after the transmission of ack.
  1368. assert(rxCmd == 0);
  1369. rxCmd = p;
  1370. ackReq = true;
  1371. break;
  1372. case 0x02: //Association response
  1373. //recv() is in charge of sending ack.
  1374. //MLME-ASSOCIATE.confirm will be passed to upper layer after the transmission of ack.
  1375. assert(rxCmd == 0);
  1376. rxCmd = p;
  1377. ackReq = true;
  1378. wph = HDR_LRWPAN(p);
  1379. rt_myNodeID = *((UINT_16 *)wph->MSDU_Payload);
  1380. #ifdef ZigBeeIF
  1381. sscs->setGetClusTreePara('g',p);
  1382. #endif
  1383. break;
  1384. case 0x03: //Disassociation notification
  1385. break;
  1386. case 0x04: //Data request
  1387. //recv() is in charge of sending ack.
  1388. //pending packet will be sent after the transmission of ack.
  1389. assert(rxCmd == 0);
  1390. rxCmd = p;
  1391. ackReq = true;
  1392. break;
  1393. case 0x05: //PAN ID conflict notification
  1394. break;
  1395. case 0x06: //Orphan notification
  1396. wph = HDR_LRWPAN(p);
  1397. sscs->MLME_ORPHAN_indication(wph->MHR_SrcAddrInfo.addr_64,false,0);
  1398. break;
  1399. case 0x07: //Beacon request
  1400. if (capability.FFD //I am an FFD
  1401.  && (mpib.macAssociationPermit) //association permitted
  1402.  && (mpib.macShortAddress != 0xffff) //allow to send beacons
  1403.  && (mpib.macBeaconOrder == 15)) //non-beacon enabled mode
  1404. {
  1405. //send a beacon using unslotted CSMA-CA
  1406. #ifdef DEBUG802_15_4
  1407. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  1408. #endif
  1409. assert(!txBcnCmd);
  1410. txBcnCmd = Packet::alloc();
  1411. if (!txBcnCmd) break;
  1412. wph = HDR_LRWPAN(txBcnCmd);
  1413. frmCtrl.FrmCtrl = 0;
  1414. frmCtrl.setFrmType(defFrmCtrl_Type_Beacon);
  1415. frmCtrl.setSecu(secuBeacon);
  1416. frmCtrl.setFrmPending(false);
  1417. frmCtrl.setAckReq(false);
  1418. frmCtrl.setDstAddrMode(defFrmCtrl_AddrModeNone);
  1419. if (mpib.macShortAddress == 0xfffe)
  1420. {
  1421. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode64);
  1422. wph->MHR_SrcAddrInfo.panID = mpib.macPANId;
  1423. wph->MHR_SrcAddrInfo.addr_64 = aExtendedAddress;
  1424. }
  1425. else
  1426. {
  1427. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode16);
  1428. wph->MHR_SrcAddrInfo.panID = mpib.macPANId;
  1429. wph->MHR_SrcAddrInfo.addr_16 = mpib.macShortAddress;
  1430. }
  1431. sfSpec.SuperSpec = 0;
  1432. sfSpec.setBO(15);
  1433. sfSpec.setBLE(mpib.macBattLifeExt);
  1434. sfSpec.setPANCoor(isPANCoor);
  1435. sfSpec.setAssoPmt(mpib.macAssociationPermit);
  1436. wph->MSDU_GTSFields.spec = 0;
  1437. wph->MSDU_PendAddrFields.spec = 0;
  1438. wph->MSDU_PayloadLen = 0;
  1439. #ifdef ZigBeeIF
  1440. sscs->setGetClusTreePara('s',txBcnCmd);
  1441. #endif
  1442. constructMPDU(4,txBcnCmd,frmCtrl.FrmCtrl,mpib.macBSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,sfSpec.SuperSpec,0,0);
  1443. hdr_dst((char *)HDR_MAC(txBcnCmd),p802_15_4macSA(p));
  1444. hdr_src((char *)HDR_MAC(txBcnCmd),index_);
  1445. HDR_CMN(txBcnCmd)->ptype() = PT_MAC;
  1446.     //for trace
  1447. HDR_CMN(txBcnCmd)->next_hop_ = p802_15_4macDA(txBcnCmd); //nam needs the nex_hop information
  1448. p802_15_4hdrBeacon(txBcnCmd);
  1449. csmacaBegin('c');
  1450. }
  1451. break;
  1452. case 0x08: //Coordinator realignment
  1453. wph = HDR_LRWPAN(p);
  1454. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  1455. frmCtrl.parse();
  1456. if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64) //directed to an orphan device
  1457. {
  1458. //recv() is in charge of sending ack.
  1459. //further handling continues after the transmission of ack.
  1460. assert(rxCmd == 0);
  1461. rxCmd = p;
  1462. ackReq = true;
  1463. }
  1464. else //broadcasted realignment command
  1465. if ((wph->MHR_SrcAddrInfo.addr_64 == macCoordExtendedAddress)
  1466. && (wph->MHR_SrcAddrInfo.panID == mpib.macPANId))
  1467. {
  1468. //no specification in the draft as how to handle this packet, so use our discretion
  1469. mpib.macPANId = *((UINT_16 *)wph->MSDU_Payload);
  1470. mpib.macCoordShortAddress = *((UINT_16 *)(wph->MSDU_Payload + 2));
  1471. tmp_ppib.phyCurrentChannel = wph->MSDU_Payload[4];
  1472. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  1473. }
  1474. break;
  1475. case 0x09: //GTS request
  1476. break;
  1477. default:
  1478. assert(0);
  1479. break;
  1480. }
  1481. if (!ackReq)
  1482. log(p);
  1483. else
  1484. log(p->refcopy());
  1485. }
  1486. void Mac802_15_4::recvData(Packet *p)
  1487. {
  1488. hdr_lrwpan* wph;
  1489. hdr_cmn* ch;
  1490. FrameCtrl frmCtrl;
  1491. UINT_8 ifs;
  1492. //pass the data packet to upper layer
  1493. //(we need some time to process the packet -- so delay SIFS/LIFS symbols from now or after finishing sending the ack.)
  1494. //(refer to Figure 60 for details of SIFS/LIFS)
  1495. assert(rxData == 0);
  1496. rxData = p;
  1497. wph = HDR_LRWPAN(p);
  1498. ch = HDR_CMN(p);
  1499. #ifdef DEBUG802_15_4
  1500. fprintf(stdout,"[%s::%s][%f](node %d) DATA (%s) received: from = %d, uid = %d, mac_uid = %ld, size = %d, SN = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),ch->uid(),wph->uid,ch->size(),wph->MHR_BDSN);
  1501. #endif
  1502. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  1503. frmCtrl.parse();
  1504. rxDataTime = CURRENT_TIME;
  1505. if (!frmCtrl.ackReq)
  1506. {
  1507. if (ch->size() <= aMaxSIFSFrameSize)
  1508. ifs = aMinSIFSPeriod;
  1509. else
  1510. ifs = aMinLIFSPeriod;
  1511. Scheduler::instance().schedule(&IFSH, &(IFSH.nullEvent), ifs/phy->getRate('s'));
  1512. }
  1513. //else //schedule and dispatch after finishing ack. transmission
  1514. }
  1515. bool Mac802_15_4::toParent(Packet *p)
  1516. {
  1517. hdr_lrwpan* wph = HDR_LRWPAN(p);
  1518. FrameCtrl frmCtrl;
  1519. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  1520. frmCtrl.parse();
  1521. if (((frmCtrl.dstAddrMode == defFrmCtrl_AddrMode16)&&(wph->MHR_DstAddrInfo.addr_16 == mpib.macCoordShortAddress))
  1522. ||  ((frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64)&&(wph->MHR_DstAddrInfo.addr_64 == mpib.macCoordExtendedAddress)))
  1523. return true;
  1524. else
  1525. return false;
  1526. }
  1527. double Mac802_15_4::locateBoundary(bool parent,double wtime)
  1528. {
  1529. //In the case that a node acts as both a coordinator and a device, 
  1530. //transmission of beacons is preferablly to be aligned with reception 
  1531. //of beacons to achieve the best results -- but we cannot control this.
  1532. //For example, the parent may originally work in non-beacon enabled mode
  1533. //and later on begin to work in beacon enabled mode; the parent will
  1534. //not align with the child since it is not supposed to handle the beacons
  1535. //from the child.
  1536. //So the alignment is specifically w.r.t. either transmission of beacons
  1537. //(as a coordinator) or reception of beacons (as a device), but there is
  1538. //no guarantee to satisfy both.
  1539. int align;
  1540. double bcnTxRxTime,bPeriod;
  1541. double newtime;
  1542. if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15))
  1543. return wtime;
  1544. if (parent)
  1545. align = (macBeaconOrder2 == 15)?1:2;
  1546. else
  1547. align = (mpib.macBeaconOrder == 15)?2:1;
  1548. bcnTxRxTime = (align == 1)?(macBcnTxTime / phy->getRate('s')):(macBcnRxTime / phy->getRate('s'));
  1549. bPeriod = aUnitBackoffPeriod / phy->getRate('s');
  1550. /* Linux floating number compatibility
  1551. newtime = fmod(CURRENT_TIME + wtime - bcnTxRxTime, bPeriod);
  1552. */
  1553. {
  1554. double tmpf;
  1555. tmpf = CURRENT_TIME + wtime;
  1556. tmpf -= bcnTxRxTime;
  1557. newtime = fmod(tmpf, bPeriod);
  1558. }
  1559. #ifdef DEBUG802_15_4
  1560. //fprintf(stdout,"[%s::%s][%f](node %d) delay = bPeriod - fmod = %f - %f = %fn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,bPeriod,newtime,bPeriod - newtime);
  1561. #endif
  1562. if(newtime > 0.000001) // 2.31 change
  1563. {
  1564. /* Linux floating number compatibility
  1565. newtime = wtime + (bPeriod - newtime);
  1566. */
  1567. {
  1568. double tmpf;
  1569. tmpf = bPeriod - newtime;
  1570. newtime = wtime + tmpf;
  1571. }
  1572. }
  1573. else
  1574. newtime = wtime;
  1575. return newtime;
  1576. }
  1577. void Mac802_15_4::txOverHandler(void)
  1578. {
  1579. assert(txPkt);
  1580. PD_DATA_confirm(p_UNDEFINED);
  1581. }
  1582. void Mac802_15_4::txHandler(void)
  1583. {
  1584. assert(txBcnCmd||txBcnCmd2||txData);
  1585. Packet *p;
  1586. hdr_lrwpan* wph;
  1587. hdr_cmn* ch;
  1588. UINT_8 t_numRetry;
  1589. if (txBcnCmd) p = txBcnCmd;
  1590. else if (txBcnCmd2) p = txBcnCmd2;
  1591. else p = txData;
  1592. wph = HDR_LRWPAN(p);
  1593. ch = HDR_CMN(p);
  1594. if (txBcnCmd) t_numRetry = numBcnCmdRetry;
  1595. else if (txBcnCmd2) t_numRetry = numBcnCmdRetry2;
  1596. else t_numRetry = numDataRetry;
  1597. t_numRetry++;
  1598. #ifdef DEBUG802_15_4
  1599. if (t_numRetry <= aMaxFrameRetries)
  1600. fprintf(stdout,"[%s::%s][%f](node %d) No ACK - retransmitting: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1601. else
  1602. fprintf(stdout,"[%s::%s][%f](node %d) No ACK - giving up: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
  1603. #endif
  1604. if (t_numRetry > aMaxFrameRetries)
  1605. nam->flashLinkFail(CURRENT_TIME,p802_15_4macDA(p));
  1606. dispatch(p_BUSY,__FUNCTION__); //the status p_BUSY will be ignore
  1607. }
  1608. void Mac802_15_4::extractHandler(void)
  1609. {
  1610. if (taskP.taskStatus(TP_mlme_associate_request))
  1611. strcpy(taskP.taskFrFunc(TP_mlme_associate_request),__FUNCTION__);
  1612. dispatch(p_BUSY,__FUNCTION__);
  1613. }
  1614. void Mac802_15_4::assoRspWaitHandler(void)
  1615. {
  1616. dispatch(p_BUSY,__FUNCTION__);
  1617. }
  1618. void Mac802_15_4::dataWaitHandler(void)
  1619. {
  1620. dispatch(p_BUSY,__FUNCTION__);
  1621. }
  1622. void Mac802_15_4::rxEnableHandler(void)
  1623. {
  1624. dispatch(p_SUCCESS,__FUNCTION__);
  1625. }
  1626. void Mac802_15_4::scanHandler(void)
  1627. {
  1628. if (taskP.mlme_scan_request_ScanType == 0x01)
  1629. taskP.taskStep(TP_mlme_scan_request)++;
  1630. dispatch(p_SUCCESS,__FUNCTION__);
  1631. }
  1632. void Mac802_15_4::beaconTxHandler(bool forTX)
  1633. {
  1634. hdr_lrwpan* wph;
  1635. FrameCtrl frmCtrl;
  1636. TRANSACLINK *tmp;
  1637. int i;
  1638. if ((mpib.macBeaconOrder != 15) //beacon enabled
  1639. || (oneMoreBeacon))
  1640. if (forTX)
  1641. {
  1642. if (capability.FFD/*&&(numberDeviceLink(&deviceLink1) > 0)*/)
  1643. {
  1644. //enable the transmitter
  1645. beaconWaiting = true;
  1646. plme_set_trx_state_request(p_FORCE_TRX_OFF); //finish your job before this!
  1647. //assert(txAck == 0); //It's not true, for the reason that packets can arrive 
  1648. //at any time if the source is in non-beacon mode.
  1649. //This could also happen if a device loses synchronization
  1650. //with its coordinator, or if a coordinator changes beacon
  1651. //order in the middle.
  1652. if (txAck)
  1653. {
  1654. #ifdef DEBUG802_15_4
  1655. if (!updateDeviceLink(tr_oper_est, &deviceLink1, &deviceLink2, p802_15_4macDA(txAck))) //this ACK is for my child
  1656. fprintf(stdout,"[%f](node %d) outgoing ACK truncated by beacon: src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn", CURRENT_TIME,index_,p802_15_4macSA(txAck),p802_15_4macDA(txAck),HDR_CMN(txAck)->uid(),HDR_LRWPAN(txAck)->uid,HDR_CMN(txAck)->size());
  1657. #endif
  1658. Packet::free(txAck);
  1659. txAck = 0;
  1660. }
  1661. plme_set_trx_state_request(p_TX_ON);
  1662. }
  1663. else
  1664. assert(0);
  1665. }
  1666. else
  1667. {
  1668. if (capability.FFD/*&&(numberDeviceLink(&deviceLink1) > 0)*/) //send a beacon here
  1669. {
  1670. //beaconWaiting = false;
  1671. if ((taskP.taskStatus(TP_mlme_start_request))
  1672. &&  (mpib.macBeaconOrder != 15))
  1673. {
  1674. if (txAck||backoffStatus == 1)
  1675. {
  1676. beaconWaiting = false;
  1677. bcnTxT->start();
  1678. return;
  1679. }
  1680. }
  1681. #ifdef DEBUG802_15_4
  1682. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBeacon:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  1683. #endif
  1684. if (updateNFailLink(fl_oper_est,index_) == 0)
  1685. {
  1686. if (txBeacon)
  1687. {
  1688. Packet::free(txBeacon);
  1689. txBeacon = 0;
  1690. }
  1691. beaconWaiting = false;
  1692. bcnTxT->start();
  1693. return;
  1694. }
  1695. assert(!txBeacon);
  1696. txBeacon = Packet::alloc();
  1697. if (!txBeacon)
  1698. {
  1699. bcnTxT->start(); //try to restore the transmission of beacons next time
  1700. return;
  1701. }
  1702. wph = HDR_LRWPAN(txBeacon);
  1703. frmCtrl.FrmCtrl = 0;
  1704. frmCtrl.setFrmType(defFrmCtrl_Type_Beacon);
  1705. frmCtrl.setSecu(secuBeacon);
  1706. frmCtrl.setAckReq(false);
  1707. frmCtrl.setDstAddrMode(defFrmCtrl_AddrModeNone);
  1708. if (mpib.macShortAddress == 0xfffe)
  1709. {
  1710. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode64);
  1711. wph->MHR_SrcAddrInfo.panID = mpib.macPANId;
  1712. wph->MHR_SrcAddrInfo.addr_64 = aExtendedAddress;
  1713. }
  1714. else
  1715. {
  1716. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode16);
  1717. wph->MHR_SrcAddrInfo.panID = mpib.macPANId;
  1718. wph->MHR_SrcAddrInfo.addr_16 = mpib.macShortAddress;
  1719. }
  1720. sfSpec.SuperSpec = 0;
  1721. sfSpec.setBO(mpib.macBeaconOrder);
  1722. sfSpec.setSO(mpib.macSuperframeOrder);
  1723. sfSpec.setFinCAP(aNumSuperframeSlots - 1); //TBD: may be less than <aNumSuperframeSlots> when considering GTS
  1724. sfSpec.setBLE(mpib.macBattLifeExt);
  1725. sfSpec.setPANCoor(isPANCoor);
  1726. sfSpec.setAssoPmt(mpib.macAssociationPermit);
  1727. //populate the GTS fields -- more TBD when considering GTS
  1728. gtsSpec.fields.spec = 0;
  1729. gtsSpec.setPermit(mpib.macGTSPermit);
  1730. wph->MSDU_GTSFields = gtsSpec.fields;
  1731. //--- populate the pending address list ---
  1732. pendAddrSpec.numShortAddr = 0;
  1733. pendAddrSpec.numExtendedAddr = 0;
  1734. purgeTransacLink(&transacLink1,&transacLink2);
  1735. tmp = transacLink1;
  1736. i = 0;
  1737. while (tmp != NULL)
  1738. {
  1739. if (tmp->pendAddrMode == defFrmCtrl_AddrMode16)
  1740. {
  1741. if (updateDeviceLink(tr_oper_est,&deviceLink1,&deviceLink2,tmp->pendAddr64) == 0)
  1742. i = pendAddrSpec.addShortAddr(tmp->pendAddr16); //duplicated address filtered out
  1743. }
  1744. else
  1745. {
  1746. if (updateDeviceLink(tr_oper_est,&deviceLink1,&deviceLink2,tmp->pendAddr64) == 0)
  1747. i = pendAddrSpec.addExtendedAddr(tmp->pendAddr64); //duplicated address filtered out
  1748. }
  1749. if (i >= 7) break;
  1750. tmp = tmp->next;
  1751. }
  1752. pendAddrSpec.format();
  1753. wph->MSDU_PendAddrFields = pendAddrSpec.fields;
  1754. frmCtrl.setFrmPending(i>0);
  1755. //To populate the beacon payload field, <macBeaconPayloadLength> and <macBeaconPayload>
  1756. //should be set first, in that order (use primitive MLME_SET_request).
  1757. wph->MSDU_PayloadLen = mpib.macBeaconPayloadLength;
  1758. memcpy(wph->MSDU_Payload,mpib.macBeaconPayload,mpib.macBeaconPayloadLength);
  1759. //-----------------------------------------
  1760. #ifdef ZigBeeIF
  1761. sscs->setGetClusTreePara('s',txBeacon);
  1762. #endif
  1763. constructMPDU(2 + gtsSpec.size() + pendAddrSpec.size() + mpib.macBeaconPayloadLength,txBeacon,frmCtrl.FrmCtrl,mpib.macBSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,sfSpec.SuperSpec,0,0);
  1764. hdr_src((char *)HDR_MAC(txBeacon),index_);
  1765. hdr_dst((char *)HDR_MAC(txBeacon),MAC_BROADCAST);
  1766. HDR_CMN(txBeacon)->ptype() = PT_MAC;
  1767. HDR_CMN(txBeacon)->next_hop_ = p802_15_4macDA(txBeacon); //nam needs the nex_hop information
  1768. p802_15_4hdrBeacon(txBeacon);
  1769. #ifdef DEBUG802_15_4
  1770. fprintf(stdout,"[%s::%s][%f](node %d) transmit BEACON to %d: SN = %d, uid = %d, mac_uid = %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macDA(txBeacon),HDR_LRWPAN(txBeacon)->MHR_BDSN,HDR_CMN(txBeacon)->uid(),HDR_LRWPAN(txBeacon)->uid);
  1771. #endif
  1772. txPkt = txBeacon;
  1773. HDR_CMN(txBeacon)->direction() = hdr_cmn::DOWN;
  1774. //nam->flashNodeMark(CURRENT_TIME);
  1775. sendDown(txBeacon->refcopy(), this);
  1776. mpib.macBeaconTxTime = (UINT_32)(CURRENT_TIME * phy->getRate('s'));
  1777. macBcnTxTime = CURRENT_TIME * phy->getRate('s'); //double used for accuracy
  1778. oneMoreBeacon = false;
  1779. }
  1780. else
  1781. assert(0);
  1782. }
  1783. 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)
  1784. }
  1785. void Mac802_15_4::beaconRxHandler(void)
  1786. {
  1787. if (macBeaconOrder2 != 15) //beacon enabled (do nothing if beacon not enabled)
  1788. {
  1789. if (txAck)
  1790. {
  1791. Packet::free(txAck);
  1792. txAck = 0;
  1793. }
  1794. //enable the receiver
  1795. plme_set_trx_state_request(p_RX_ON);
  1796. if (taskP.mlme_sync_request_tracking)
  1797. {
  1798. //a better way is using another timer to detect <numLostBeacons> right after the header of superframe
  1799. if (numLostBeacons > aMaxLostBeacons)
  1800. {
  1801. char label[11];
  1802. //label[0] = 0;
  1803. strcpy(label,"" "");
  1804. #ifdef ZigBeeIF
  1805. if (sscs->t_isCT)
  1806. sprintf(label,""%s"",(sscs->RNType())?"+":"-");
  1807. #endif
  1808. nam->changeLabel(CURRENT_TIME,label);
  1809. changeNodeColor(CURRENT_TIME,Nam802_15_4::def_Node_clr);
  1810. sscs->MLME_SYNC_LOSS_indication(m_BEACON_LOSS);
  1811. numLostBeacons = 0;
  1812. }
  1813. else
  1814. {
  1815. numLostBeacons++;
  1816. bcnRxT->start();
  1817. }
  1818. }
  1819. }
  1820. }
  1821. void Mac802_15_4::beaconSearchHandler(void)
  1822. {
  1823. dispatch(p_BUSY,__FUNCTION__);
  1824. }
  1825. void Mac802_15_4::isPanCoor(bool isPC)
  1826. {
  1827. if (isPANCoor == isPC)
  1828. return;
  1829. if (isPC)
  1830. changeNodeColor(CURRENT_TIME,Nam802_15_4::def_PANCoor_clr);
  1831. else if (isPANCoor)
  1832. changeNodeColor(CURRENT_TIME,
  1833.    (mpib.macPANId == 0xffff) ? Nam802_15_4::def_Node_clr :
  1834.    (mpib.macAssociationPermit) ? Nam802_15_4::def_Coor_clr : Nam802_15_4::def_Dev_clr);
  1835. isPANCoor = isPC;
  1836. }
  1837. //-------------------------------------------------------------------------------------
  1838. void Mac802_15_4::set_trx_state_request(PHYenum state,const char *frFile,const char *frFunc,int line)
  1839. {
  1840. #ifdef DEBUG802_15_4
  1841. fprintf(stdout,"[%s::%s][%f](node %d): %s request from [%s:%s:%d]n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,
  1842. (state == p_RX_ON)?"RX_ON":
  1843. (state == p_TX_ON)?"TX_ON":
  1844. (state == p_TRX_OFF)?"TRX_OFF":
  1845. (state == p_FORCE_TRX_OFF)?"FORCE_TRX_OFF":"???",
  1846. frFile,frFunc,line);
  1847. #endif
  1848. trx_state_req = state;
  1849. phy->PLME_SET_TRX_STATE_request(state);
  1850. }
  1851. char *taskName[] = {"NONE",
  1852.     "MCPS-DATA.request",
  1853.     "MLME-ASSOCIATE.request",
  1854.     "MLME-ASSOCIATE.response",
  1855.     "MLME-DISASSOCIATE.request",
  1856.     "MLME-ORPHAN.response",
  1857.     "MLME-RESET.request",
  1858.     "MLME-RX-ENABLE.request",
  1859.     "MLME-SCAN.request",
  1860.     "MLME-START.request",
  1861.     "MLME-SYNC.request",
  1862.     "MLME-POLL.request",
  1863.     "CCA_csmaca",
  1864.     "RX_ON_csmaca"};
  1865. void Mac802_15_4::checkTaskOverflow(UINT_8 task)
  1866. {
  1867. //Though we assume the upper layer should know what it is doing -- should send down requests one by one.
  1868. //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)
  1869. if (taskP.taskStatus(task))
  1870. {
  1871. fprintf(stdout,"[%s::%s][%f](node %d) task overflow: %sn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,taskName[task]);
  1872. exit(1);
  1873. }
  1874. else
  1875. {
  1876. taskP.taskStep(task) = 0;
  1877. (taskP.taskFrFunc(task))[0] = 0;
  1878. }
  1879. }
  1880. void Mac802_15_4::dispatch(PHYenum status,const char *frFunc,PHYenum req_state,MACenum mStatus)
  1881. {
  1882. hdr_lrwpan *wph;
  1883. hdr_cmn *ch;
  1884. FrameCtrl frmCtrl;
  1885. UINT_8 ifs;
  1886. //int i;
  1887. if (strcmp(frFunc,"csmacaCallBack") == 0)
  1888. {
  1889. if (txCsmaca == txBcnCmd2)
  1890. {
  1891. if (taskP.taskStatus(TP_mlme_scan_request)
  1892. && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
  1893. {
  1894. if ((taskP.mlme_scan_request_ScanType == 0x01) //active scan
  1895. ||  (taskP.mlme_scan_request_ScanType == 0x03)) //orphan scan
  1896. mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
  1897. }
  1898. else if (taskP.taskStatus(TP_mlme_start_request)
  1899. && (strcmp(taskP.taskFrFunc(TP_mlme_start_request),frFunc) == 0))
  1900. 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);
  1901. else if (taskP.taskStatus(TP_mlme_associate_request)
  1902. && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
  1903. mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,status);
  1904. else if (taskP.taskStatus(TP_mlme_poll_request)
  1905. && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),frFunc) == 0))
  1906. 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);
  1907. else //default handling for txBcnCmd2
  1908. {
  1909. if (status == p_IDLE)
  1910. plme_set_trx_state_request(p_TX_ON);
  1911. else
  1912. {
  1913. freePkt(txBcnCmd2);
  1914. txBcnCmd2 = 0;
  1915. csmacaResume(); //other packet may be waiting
  1916. }
  1917. }
  1918. }
  1919. else if (txCsmaca == txData)
  1920. {
  1921. assert(taskP.taskStatus(TP_mcps_data_request)
  1922. && (strcmp(taskP.taskFrFunc(TP_mcps_data_request),frFunc) == 0));
  1923. if (taskP.mcps_data_request_TxOptions & TxOp_GTS) //GTS transmission
  1924. {
  1925. ; //TBD
  1926. }
  1927. else if ((taskP.mcps_data_request_TxOptions & TxOp_Indirect) //indirect transmission
  1928. && (capability.FFD&&(numberDeviceLink(&deviceLink1) > 0))) //I am a coordinator
  1929. {
  1930. if (status != p_IDLE)
  1931. mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_BUSY,m_CHANNEL_ACCESS_FAILURE);
  1932. else
  1933. {
  1934. strcpy(taskP.taskFrFunc(TP_mcps_data_request),"PD_DATA_confirm");
  1935. plme_set_trx_state_request(p_TX_ON);
  1936. }
  1937. }
  1938. else //direct transmission: in this case, let mcps_data_request() take care of everything
  1939. mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,status);
  1940. }
  1941. else if (txCsmaca == txBcnCmd) //default handling for txBcnCmd
  1942. {
  1943. wph = HDR_LRWPAN(txBcnCmd);
  1944. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  1945. frmCtrl.parse();
  1946. if (status == p_IDLE)
  1947. {
  1948. if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd) //command packet
  1949. && (wph->MSDU_CmdType == 0x02)) //association response packet
  1950. strcpy(taskP.taskFrFunc(TP_mlme_associate_response),"PD_DATA_confirm");
  1951. else if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd) //command packet
  1952. && (wph->MSDU_CmdType == 0x08)) //coordinator realignment response packet
  1953. strcpy(taskP.taskFrFunc(TP_mlme_orphan_response),"PD_DATA_confirm");
  1954. plme_set_trx_state_request(p_TX_ON);
  1955. }
  1956. else
  1957. {
  1958. if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd) //command packet
  1959. && (wph->MSDU_CmdType == 0x02)) //association response packet
  1960. 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
  1961. else if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd) //command packet
  1962. && (wph->MSDU_CmdType == 0x08)) //coordinator realignment response packet
  1963. mlme_orphan_response(taskP.mlme_orphan_response_OrphanAddress,0,true,false,false,p_BUSY);
  1964. else
  1965. {
  1966. freePkt(txBcnCmd);
  1967. txBcnCmd = 0;
  1968. csmacaResume(); //other packets may be waiting
  1969. }
  1970. }
  1971. }
  1972. //else //may be purged from pending list
  1973. }
  1974. else if (strcmp(frFunc,"PD_DATA_confirm") == 0)
  1975. {
  1976. if (txPkt == txBeacon)
  1977. {
  1978. if (taskP.taskStatus(TP_mlme_start_request)
  1979. && (strcmp(taskP.taskFrFunc(TP_mlme_start_request),frFunc) == 0))
  1980. 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);
  1981. else //default handling
  1982. {
  1983. resetTRX();
  1984. taskSuccess('b');
  1985. }
  1986. }
  1987. else if (txPkt == txAck)
  1988. {
  1989. if (rxCmd)
  1990. {
  1991. ch = HDR_CMN(rxCmd);
  1992. if (ch->size() <= aMaxSIFSFrameSize)
  1993. ifs = aMinSIFSPeriod;
  1994. else
  1995. ifs = aMinLIFSPeriod;
  1996. Scheduler::instance().schedule(&IFSH, &(IFSH.nullEvent), ifs/phy->getRate('s'));
  1997. resetTRX();
  1998. taskSuccess('a');
  1999. }
  2000. else if (rxData) //default handling (virtually the only handling needed) for <rxData>
  2001. {
  2002. ch = HDR_CMN(rxData);
  2003. if (ch->size() <= aMaxSIFSFrameSize)
  2004. ifs = aMinSIFSPeriod;
  2005. else
  2006. ifs = aMinLIFSPeriod;
  2007. Scheduler::instance().schedule(&IFSH, &(IFSH.nullEvent), ifs/phy->getRate('s'));
  2008. resetTRX();
  2009. taskSuccess('a');
  2010. }
  2011. else //ack. for duplicated packet
  2012. {
  2013. resetTRX();
  2014. taskSuccess('a');
  2015. }
  2016. }
  2017. else if (txPkt == txBcnCmd)
  2018. {
  2019. //default handling -- should be replaced once a specific task will handle this
  2020. wph = HDR_LRWPAN(txBcnCmd);
  2021. ch = HDR_CMN(txBcnCmd);
  2022. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2023. frmCtrl.parse();
  2024. if (frmCtrl.ackReq) //ack. required
  2025. {
  2026. //enable the receiver
  2027. plme_set_trx_state_request(p_RX_ON);
  2028. txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
  2029. waitBcnCmdAck = true;
  2030. }
  2031. else //assume success if ack. not required
  2032. {
  2033. resetTRX();
  2034. taskSuccess('c');
  2035. }
  2036. }
  2037. else if (txPkt == txBcnCmd2)
  2038. {
  2039. if (taskP.taskStatus(TP_mlme_scan_request)
  2040. && ((taskP.mlme_scan_request_ScanType == 0x01) //active scan
  2041.   ||(taskP.mlme_scan_request_ScanType == 0x03)) //orphan scan
  2042. && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
  2043. mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
  2044. else if (taskP.taskStatus(TP_mlme_start_request)
  2045. && (strcmp(taskP.taskFrFunc(TP_mlme_start_request),frFunc) == 0))
  2046. 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);
  2047. else if (taskP.taskStatus(TP_mlme_associate_request)
  2048. && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
  2049. mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,status);
  2050. else if (taskP.taskStatus(TP_mlme_poll_request)
  2051. && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),frFunc) == 0))
  2052. 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);
  2053. else //default handling
  2054. {
  2055. wph = HDR_LRWPAN(txBcnCmd2);
  2056. ch = HDR_CMN(txBcnCmd2);
  2057. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2058. frmCtrl.parse();
  2059. if (frmCtrl.ackReq) //ack. required
  2060. {
  2061. //enable the receiver
  2062. plme_set_trx_state_request(p_RX_ON);
  2063. txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
  2064. waitBcnCmdAck2 = true;
  2065. }
  2066. else //assume success if ack. not required
  2067. {
  2068. resetTRX();
  2069. taskSuccess('C');
  2070. }
  2071. }
  2072. }
  2073. else if (txPkt == txData)
  2074. {
  2075. assert((taskP.taskStatus(TP_mcps_data_request))
  2076. && (strcmp(taskP.taskFrFunc(TP_mcps_data_request),frFunc) == 0));
  2077. wph = HDR_LRWPAN(txData);
  2078. ch = HDR_CMN(txData);
  2079. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2080. frmCtrl.parse();
  2081. if (taskP.taskStatus(TP_mcps_data_request))
  2082. {
  2083. if (taskP.mcps_data_request_TxOptions & TxOp_GTS) //GTS transmission
  2084. {
  2085. ; //TBD
  2086. }
  2087. else if ((taskP.mcps_data_request_TxOptions & TxOp_Indirect) //indirect transmission
  2088. && (capability.FFD&&(numberDeviceLink(&deviceLink1) > 0))) //I am a coordinator
  2089. {
  2090. if (!frmCtrl.ackReq) //ack. not required
  2091. mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_SUCCESS);
  2092. else
  2093. {
  2094. strcpy(taskP.taskFrFunc(TP_mcps_data_request),"recvAck");
  2095. //enable the receiver
  2096. plme_set_trx_state_request(p_RX_ON);
  2097. txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
  2098. waitDataAck = true;
  2099. }
  2100. }
  2101. else //direct transmission: in this case, let mcps_data_request() take care of everything
  2102. mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,status);
  2103. }
  2104. else //default handling (seems impossible)
  2105. {
  2106. if (frmCtrl.ackReq) //ack. required
  2107. {
  2108. //enable the receiver
  2109. plme_set_trx_state_request(p_RX_ON);
  2110. txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
  2111. waitDataAck = true;
  2112. }
  2113. else //assume success if ack. not required
  2114. {
  2115. resetTRX();
  2116. taskSuccess('d');
  2117. }
  2118. }
  2119. }
  2120. //else //may be purged from pending list
  2121. }
  2122. else if (strcmp(frFunc,"recvAck") == 0) //always check the task status if the dispatch comes from recvAck()
  2123. {
  2124. if (txPkt == txData)
  2125. {
  2126. if ((taskP.taskStatus(TP_mcps_data_request))
  2127.    && (strcmp(taskP.taskFrFunc(TP_mcps_data_request),frFunc) == 0))
  2128. mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_SUCCESS);
  2129. else //default handling for <txData>
  2130. {
  2131. if (taskP.taskStatus(TP_mcps_data_request)) //seems late ACK received
  2132. taskP.taskStatus(TP_mcps_data_request) = false;
  2133. resetTRX();
  2134. taskSuccess('d');
  2135. }
  2136. }
  2137. else if (txPkt == txBcnCmd2)
  2138. {
  2139. if (taskP.taskStatus(TP_mlme_associate_request)
  2140.   && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
  2141. mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,p_SUCCESS);
  2142. else if (taskP.taskStatus(TP_mlme_poll_request)
  2143.   && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),frFunc) == 0))
  2144. 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);
  2145. else //default handling for <txBcnCmd2>
  2146. taskSuccess('C');
  2147. }
  2148. else if (txPkt == txBcnCmd) //default handling for <txBcnCmd>
  2149. {
  2150. wph = HDR_LRWPAN(txBcnCmd);
  2151. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2152. frmCtrl.parse();
  2153. if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd) //command packet
  2154.  && (wph->MSDU_CmdType == 0x02)) //association response packet
  2155. mlme_associate_response(taskP.mlme_associate_response_DeviceAddress,0,m_SUCCESS,0,false,p_SUCCESS);
  2156. else if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd) //command packet
  2157. && (wph->MSDU_CmdType == 0x08)) //coordinator realignment response packet
  2158. mlme_orphan_response(taskP.mlme_orphan_response_OrphanAddress,0,true,false,false);
  2159. else
  2160. taskSuccess('c');
  2161. }
  2162. //else //may be purged from pending list
  2163. }
  2164. else if (strcmp(frFunc,"txHandler") == 0) //always check the task status if the dispatch comes from a timer
  2165. {
  2166. if (txPkt == txData)
  2167. {
  2168. if ((!taskP.taskStatus(TP_mcps_data_request))
  2169.    || (strcmp(taskP.taskFrFunc(TP_mcps_data_request),"recvAck") != 0))
  2170.     return;
  2171. if (taskP.taskStatus(TP_mcps_data_request))
  2172. if (taskP.mcps_data_request_TxOptions & TxOp_GTS) //GTS transmission
  2173. {
  2174. ; //TBD
  2175. }
  2176. else if ((taskP.mcps_data_request_TxOptions & TxOp_Indirect) //indirect transmission
  2177. && (capability.FFD&&(numberDeviceLink(&deviceLink1) > 0))) //I am a coordinator
  2178. {
  2179. /*
  2180. //there is contradiction in the draft:
  2181. //page 156, line 16: (for transaction, i.e., indirect transmission) "all subsequent retransmissions shall be transmitted using CSMA-CA"
  2182. //page 158, line 14-16:
  2183. // "if a single transmission attempt has failed and the transmission was indirect, the coordinator shall not
  2184. // retransmit the data or MAC command frame. Instead, the frame shall remain in the transaction queue of the
  2185. // coordinator."
  2186. //the description on page 158 is more reasonable (though we already proceeded according to page 156)
  2187. // now follow page 158
  2188. numDataRetry++;
  2189. if (numDataRetry <= aMaxFrameRetries)
  2190. {
  2191. //no need to check if the packet has been purged -- if purged, then taskFailed() should have set txData = 0
  2192. wph = HDR_LRWPAN(txData);
  2193. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2194. frmCtrl.parse();
  2195. i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,txData);
  2196. if (i != 0) //already purged from pending list
  2197. {
  2198. Packet::free(txData);
  2199. txData = 0;
  2200. return;
  2201. }
  2202. // -- don't end here, but afte 'else'
  2203. waitDataAck = false;
  2204. csmacaResume();
  2205. }
  2206. else
  2207. */
  2208. mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_BUSY,m_NO_ACK);
  2209. }
  2210. else //direct transmission: in this case, let mcps_data_request() take care of everything
  2211. 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
  2212. }
  2213. else if (txPkt == txBcnCmd2)
  2214. {
  2215. if (taskP.taskStatus(TP_mlme_associate_request)
  2216.     && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),"recvAck") == 0))
  2217. mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,p_BUSY); //status can anything but p_SUCCESS
  2218. else if (taskP.taskStatus(TP_mlme_poll_request)
  2219.   && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),"recvAck") == 0))
  2220. 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
  2221. else //default handling for <txBcnCmd2>
  2222. {
  2223. numBcnCmdRetry2++;
  2224. if (numBcnCmdRetry2 <= aMaxFrameRetries)
  2225. waitBcnCmdAck2 = false;
  2226. else
  2227. {
  2228. freePkt(txBcnCmd2);
  2229. txBcnCmd2 = 0;
  2230. }
  2231. csmacaResume(); //other packets may be waiting
  2232. }
  2233. }
  2234. else if (txPkt == txBcnCmd)
  2235. {
  2236. wph = HDR_LRWPAN(txBcnCmd);
  2237. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2238. frmCtrl.parse();
  2239. if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd) //command packet
  2240.  && (wph->MSDU_CmdType == 0x02)) //association response packet
  2241. {
  2242. //different from data packet, association response packet
  2243. //should be retransmitted though it uses indirect transmission
  2244. //(refer to page 67, line 28-32)
  2245. numBcnCmdRetry++;
  2246. if (numBcnCmdRetry <= aMaxFrameRetries)
  2247. {
  2248. /* no need to check if the packet has been purged -- if purged, then taskFailed() should have set txBcnCmd = 0
  2249. if (wph->indirect) //indirect transmission
  2250. {
  2251. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2252. frmCtrl.parse();
  2253. i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,txBcnCmd);
  2254. if (i != 0) //already purged from pending list
  2255. {
  2256. Packet::free(txBcnCmd);
  2257. txBcnCmd = 0;
  2258. return;
  2259. }
  2260. }
  2261. */
  2262. strcpy(taskP.taskFrFunc(TP_mlme_associate_response),"csmacaCallBack");
  2263. waitBcnCmdAck = false;
  2264. csmacaResume();
  2265. }
  2266. else
  2267. mlme_associate_response(taskP.mlme_associate_response_DeviceAddress,0,m_NO_ACK,0,false,p_BUSY); //status returned in MACenum rather than in PHYenum
  2268. }
  2269. else if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd) //command packet
  2270. && (wph->MSDU_CmdType == 0x08)) //coordinator realignment response packet
  2271. {
  2272. numBcnCmdRetry++;
  2273. if (numBcnCmdRetry <= aMaxFrameRetries)
  2274. {
  2275. strcpy(taskP.taskFrFunc(TP_mlme_orphan_response),"csmacaCallBack");
  2276. waitBcnCmdAck = false;
  2277. csmacaResume();
  2278. }
  2279. else
  2280. mlme_orphan_response(taskP.mlme_orphan_response_OrphanAddress,0,true,false,p_BUSY);
  2281. }
  2282. else //default handling for <txBcnCmd>
  2283. {
  2284. freePkt(txBcnCmd);
  2285. txBcnCmd = 0;
  2286. csmacaResume(); //other packets may be waiting
  2287. }
  2288. }
  2289. //else //may be purged from the pending list
  2290. }
  2291. else if (strcmp(frFunc,"PLME_SET_TRX_STATE_confirm") == 0)
  2292. {
  2293. //handle TRX_OFF
  2294. if (req_state == p_TRX_OFF)
  2295. if (taskP.taskStatus(TP_mlme_reset_request)
  2296.   && (strcmp(taskP.taskFrFunc(TP_mlme_reset_request),frFunc) == 0))
  2297. mlme_reset_request(taskP.mlme_reset_request_SetDefaultPIB,false,status);
  2298. //handle RX_ON
  2299. if (req_state == p_RX_ON)
  2300. if (taskP.taskStatus(TP_mlme_scan_request)
  2301.   && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
  2302. mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
  2303. else if (taskP.taskStatus(TP_mlme_rx_enable_request)
  2304.   && (strcmp(taskP.taskFrFunc(TP_mlme_rx_enable_request),frFunc) == 0))
  2305. mlme_rx_enable_request(0,taskP.mlme_rx_enable_request_RxOnTime,taskP.mlme_rx_enable_request_RxOnDuration,false);
  2306. }
  2307. else if (strcmp(frFunc,"PLME_SET_confirm") == 0)
  2308. {
  2309. if (taskP.taskStatus(TP_mlme_scan_request)
  2310.   && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
  2311. mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
  2312. }
  2313. else if (strcmp(frFunc,"PLME_ED_confirm") == 0)
  2314. {
  2315. if (taskP.taskStatus(TP_mlme_scan_request)
  2316. && (taskP.mlme_scan_request_ScanType == 0x00) //ED scan
  2317.   && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
  2318. mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
  2319. }
  2320. else if (strcmp(frFunc,"recvBeacon") == 0)
  2321. {
  2322. if (taskP.taskStatus(TP_mlme_scan_request)
  2323.   && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
  2324. mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,p_SUCCESS);
  2325. else if (taskP.taskStatus(TP_mlme_rx_enable_request)
  2326.   && (strcmp(taskP.taskFrFunc(TP_mlme_rx_enable_request),frFunc) == 0))
  2327. mlme_rx_enable_request(0,taskP.mlme_rx_enable_request_RxOnTime,taskP.mlme_rx_enable_request_RxOnDuration,false);
  2328. else if (taskP.taskStatus(TP_mlme_sync_request)
  2329.   && (strcmp(taskP.taskFrFunc(TP_mlme_sync_request),frFunc) == 0))
  2330. mlme_sync_request(0,taskP.mlme_sync_request_tracking,false,p_SUCCESS);
  2331. }
  2332. else if (strcmp(frFunc,"scanHandler") == 0) //always check the task status if the dispatch comes from a timer
  2333. {
  2334. if (taskP.taskStatus(TP_mlme_scan_request))
  2335. mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,p_BUSY);
  2336. }
  2337. else if (strcmp(frFunc,"extractHandler") == 0) //always check the task status if the dispatch comes from a timer
  2338. {
  2339. if (taskP.taskStatus(TP_mlme_associate_request)
  2340.   && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
  2341.   {
  2342. 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
  2343. }
  2344. else if (taskP.taskStatus(TP_mlme_poll_request)
  2345.   && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),"IFSHandler") == 0))
  2346. 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);
  2347. }
  2348. else if (strcmp(frFunc,"assoRspWaitHandler") == 0) //always check the task status if the dispatch comes from a timer
  2349. {
  2350. if (taskP.taskStatus(TP_mlme_associate_response))
  2351. {
  2352. taskP.taskStep(TP_mlme_associate_response) = 2;
  2353. mlme_associate_response(taskP.mlme_associate_response_DeviceAddress,0,m_SUCCESS,0,false,p_BUSY); //status ignored
  2354. }
  2355. }
  2356. else if (strcmp(frFunc,"dataWaitHandler") == 0) //always check the task status if the dispatch comes from a timer
  2357. {
  2358. if (taskP.taskStatus(TP_mcps_data_request))
  2359. {
  2360. taskP.taskStep(TP_mcps_data_request) = 2;
  2361. mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_BUSY); //status ignored
  2362. }
  2363. }
  2364. else if (strcmp(frFunc,"IFSHandler") == 0) //always check the task status if the dispatch comes from a timer
  2365. {
  2366. if (taskP.taskStatus(TP_mlme_associate_request)
  2367.   && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
  2368. mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,p_SUCCESS,mStatus);
  2369. else if (taskP.taskStatus(TP_mlme_poll_request)
  2370.   && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),frFunc) == 0))
  2371. 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);
  2372. else if (taskP.taskStatus(TP_mlme_scan_request)
  2373.   && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
  2374. mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,p_SUCCESS);
  2375. }
  2376. else if (strcmp(frFunc,"rxEnableHandler") == 0)
  2377. {
  2378. //if (taskP.taskStatus(TP_mlme_rx_enable_request)) //we don't check the task status (it may be reset)
  2379.   if (strcmp(taskP.taskFrFunc(TP_mlme_rx_enable_request),frFunc) == 0)
  2380. mlme_rx_enable_request(0,taskP.mlme_rx_enable_request_RxOnTime,taskP.mlme_rx_enable_request_RxOnDuration,false);
  2381. }
  2382. else if (strcmp(frFunc,"beaconSearchHandler") == 0) //always check the task status if the dispatch comes from a timer
  2383. {
  2384. if (taskP.taskStatus(TP_mlme_sync_request)
  2385.   && (strcmp(taskP.taskFrFunc(TP_mlme_sync_request),"recvBeacon") == 0))
  2386. mlme_sync_request(0,taskP.mlme_sync_request_tracking,false,p_BUSY); //status can anything but p_SUCCESS
  2387. }
  2388. }
  2389. void Mac802_15_4::sendDown(Packet *p,Handler* h)
  2390. {
  2391. if (updateNFailLink(fl_oper_est,index_) == 0)
  2392. {
  2393. if (txBeacon)
  2394. {
  2395. beaconWaiting = false;
  2396. Packet::free(txBeacon);
  2397. txBeacon = 0;
  2398. }
  2399. return;
  2400. }
  2401. else if (updateLFailLink(fl_oper_est,index_,p802_15_4macDA(p)) == 0)
  2402. {
  2403. dispatch(p_UNDEFINED,"PD_DATA_confirm");
  2404. return;
  2405. }
  2406. inTransmission = true;
  2407. //double trx_time = phy->trxTime(p,false);
  2408. /* Linux floating number compatibility
  2409. txOverT->start(trx_time + 1/phy->getRate('s'));
  2410. */
  2411. //{
  2412. //double tmpf;
  2413. //tmpf = 1/phy->getRate('s');
  2414. //txOverT->start(trx_time + tmpf);
  2415. //}
  2416. EnergyModel *em = netif_->node()->energy_model();
  2417. if (em)
  2418. if (em->energy() <= 0)
  2419. {
  2420. PD_DATA_confirm(p_UNDEFINED);
  2421. return;
  2422. }
  2423. downtarget_->recv(p, h);
  2424. }
  2425. void Mac802_15_4::mcps_data_request(UINT_8 SrcAddrMode,UINT_16 SrcPANId,IE3ADDR SrcAddr,
  2426.     UINT_8 DstAddrMode,UINT_16 DstPANId,IE3ADDR DstAddr,
  2427.     UINT_8 msduLength,Packet *msdu,UINT_8 msduHandle,UINT_8 TxOptions,
  2428.     bool frUpper,PHYenum status,MACenum mStatus)
  2429. {
  2430. UINT_8 step,task;
  2431. hdr_lrwpan *wph;
  2432. hdr_cmn *ch;
  2433. FrameCtrl frmCtrl;
  2434. double kpTime;
  2435. int i;
  2436. EnergyModel *em = netif_->node()->energy_model();
  2437. task = TP_mcps_data_request;
  2438. if (frUpper) checkTaskOverflow(task);
  2439. step = taskP.taskStep(task);
  2440. if (step == 0)
  2441. {
  2442. //check if parameters valid or not
  2443. ch = HDR_CMN(msdu);
  2444. if (ch->ptype() == PT_MAC) //we only check for 802.15.4 packets (let other packets go through -- must be changed in implementation)
  2445. if ((SrcAddrMode > 0x03)
  2446. ||(DstAddrMode > 0x03)
  2447. ||(msduLength > aMaxMACFrameSize)
  2448. ||(TxOptions > 0x0f))
  2449. {
  2450. sscs->MCPS_DATA_confirm(msduHandle,m_INVALID_PARAMETER);
  2451. return;
  2452. }
  2453. taskP.taskStatus(task) = true;
  2454. taskP.mcps_data_request_TxOptions = TxOptions;
  2455. //---construct a MPDU packet (not really a new packet in simulation, but still <msdu>)---
  2456. frmCtrl.FrmCtrl = 0;
  2457. frmCtrl.setFrmType(defFrmCtrl_Type_Data); //data type
  2458. if (TxOptions & TxOp_Acked)
  2459. frmCtrl.setAckReq(true);
  2460. if (SrcPANId == DstPANId)
  2461. frmCtrl.setIntraPan(true); //Intra PAN
  2462. frmCtrl.setDstAddrMode(DstAddrMode); //we reverse the bit order -- note to use the required order in implementation
  2463. frmCtrl.setSrcAddrMode(SrcAddrMode); //we reverse the bit order -- note to use the required order in implementation
  2464. wph = HDR_LRWPAN(msdu);
  2465. wph->MHR_DstAddrInfo.panID = DstPANId;
  2466. wph->MHR_DstAddrInfo.addr_64 = DstAddr; //it doesn't matter if this is actually a 16-bit address
  2467. wph->MHR_SrcAddrInfo.panID = SrcPANId;
  2468. wph->MHR_SrcAddrInfo.addr_64 = SrcAddr; //it doesn't matter if this is actually a 16-bit address
  2469. //ignore FCS in simulation
  2470. constructMPDU(msduLength,msdu,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0,0);
  2471. //for trace
  2472. p802_15_4hdrDATA(msdu);
  2473. //---------------------------------------------------------------------------------------------------
  2474. //perform security task if required (ignored in simulation)
  2475. }
  2476. if (TxOptions & TxOp_GTS) //GTS transmission
  2477. {
  2478. switch(step)
  2479. {
  2480. //other cases: TBD
  2481. default:
  2482. break;
  2483. }
  2484. }
  2485. else if ((TxOptions & TxOp_Indirect) //indirect transmission
  2486. && (capability.FFD&&(numberDeviceLink(&deviceLink1) > 0))) //I am a coordinator
  2487. {
  2488. switch(step)
  2489. {
  2490. case 0:
  2491. taskP.taskStep(task)++;
  2492. taskP.mcps_data_request_pendPkt = msdu;
  2493. if ((DstAddrMode == defFrmCtrl_AddrMode16) //16-bit address available
  2494. || (DstAddrMode == defFrmCtrl_AddrMode64)) //64-bit address available
  2495. {
  2496. /* Linux floating number compatibility
  2497. kpTime = mpib.macTransactionPersistenceTime * (aBaseSuperframeDuration * (1 << mpib.macBeaconOrder) / phy->getRate('s'));
  2498. */
  2499. {
  2500. double tmpf;
  2501. tmpf = (aBaseSuperframeDuration * (1 << mpib.macBeaconOrder) / phy->getRate('s'));
  2502. kpTime = mpib.macTransactionPersistenceTime * tmpf;
  2503. }
  2504. chkAddTransacLink(&transacLink1,&transacLink2,DstAddrMode,DstAddr,msdu,msduHandle,kpTime);
  2505. }
  2506. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  2507. dataWaitT->start(kpTime);
  2508. break;
  2509. case 1:
  2510. if (!taskP.taskStatus(task))
  2511. break;
  2512. if (status == p_SUCCESS) //data packet transmitted and, if required, ack. received 
  2513. {
  2514. dataWaitT->stop();
  2515. taskP.taskStatus(task) = false;
  2516. resetTRX();
  2517. taskSuccess('d');
  2518. }
  2519. else //data packet transmission failed
  2520. {
  2521. //leave the packet in the queue waiting for next polling
  2522. strcpy(taskP.taskFrFunc(task),"csmacaCallBack"); //wait for next polling
  2523. //status return in MACenum, either CHANNEL_ACCESS_FAILURE or NO_ACK
  2524. //taskP.taskStatus(task) = false;
  2525. resetTRX();
  2526. taskFailed('d',mStatus);
  2527. }
  2528. break;
  2529. case 2:
  2530. if (!taskP.taskStatus(task))
  2531. break;
  2532. taskP.taskStatus(task) = false;
  2533. //check if the transaction still pending -- actually no need to check (it must be pending if case 1 didn't happen), but no harm
  2534. 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
  2535. if (i == 0) //still pending
  2536. {
  2537. //get a copy of the packet for taskFailed()
  2538. if (!txData)
  2539. txData = taskP.mcps_data_request_pendPkt->copy();
  2540. //delete the packet from the transaction list immediately -- prevent the packet from being transmitted at the last moment
  2541. updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,taskP.mcps_data_request_pendPkt);
  2542. resetTRX();
  2543. taskFailed('d',m_TRANSACTION_EXPIRED);
  2544. return;
  2545. }
  2546. else //being successfully extracted
  2547. {
  2548. resetTRX();
  2549. taskFailed('d',m_SUCCESS);
  2550. return;
  2551. }
  2552. break;
  2553. default:
  2554. break;
  2555. }
  2556. }
  2557. else //direct transmission
  2558. {
  2559. switch(step)
  2560. {
  2561. case 0:
  2562. taskP.taskStep(task)++;
  2563. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  2564. assert(!txData);
  2565. txData = msdu;
  2566. csmacaBegin('d');
  2567. break;
  2568. case 1:
  2569. if (status == p_IDLE)
  2570. {
  2571. taskP.taskStep(task)++;
  2572. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
  2573. //enable the transmitter
  2574. plme_set_trx_state_request(p_TX_ON);
  2575. }
  2576. else
  2577. {
  2578. wph = HDR_LRWPAN(txData);
  2579. ch = HDR_CMN(txData);
  2580. if (wph->msduHandle) //from SSCS
  2581. {
  2582. //let the upper layer handle the failure (no retry)
  2583. taskP.taskStatus(task) = false;
  2584. resetTRX();
  2585. taskFailed('d',m_CHANNEL_ACCESS_FAILURE);
  2586. }
  2587. else
  2588. {
  2589. //  2.31 change. An access failure needs to be  reported here. Earlier csmacaResume() was being  called indefinetely. This has been commented and  the folowing 3 lines of code have been added  within else.
  2590. // csmacaResume();
  2591. taskP.taskStatus(task) = false;
  2592. resetTRX();
  2593. taskFailed('d',m_CHANNEL_ACCESS_FAILURE,0);
  2594. #ifdef SHUTDOWN
  2595. if ((em) && ((!capability.FFD)||(numberDeviceLink(&deviceLink1) == 0)) && (NOW>phy->T_sleep_)){ //I can sleep only if i am not a coordinator
  2596. phy->putNodeToSleep();
  2597. }
  2598. #endif
  2599. }
  2600. }
  2601. break;
  2602. case 2:
  2603. wph = HDR_LRWPAN(txData);