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

通讯编程

开发平台:

Visual C++

  1. ch = HDR_CMN(txData);
  2. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  3. frmCtrl.parse();
  4. if (frmCtrl.ackReq) //ack. required
  5. {
  6. taskP.taskStep(task)++;
  7. strcpy(taskP.taskFrFunc(task),"recvAck");
  8. //enable the receiver
  9. plme_set_trx_state_request(p_RX_ON);
  10. txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
  11. waitDataAck = true;
  12. }
  13. else //assume success if ack. not required
  14. {
  15. taskP.taskStatus(task) = false;
  16. resetTRX();
  17. taskSuccess('d');
  18. // 2.31 change: added this to put the node to sleep after successful pkt tx
  19. #ifdef SHUTDOWN
  20. if ((em) && ((!capability.FFD)||(numberDeviceLink(&deviceLink1) == 0)) && (NOW>phy->T_sleep_)){ //I can sleep only if i am not a coordinator
  21. phy->putNodeToSleep();
  22. }
  23. #endif
  24. }
  25. break;
  26. case 3:
  27. if (status == p_SUCCESS) //ack. received
  28. {
  29. taskP.taskStatus(task) = false;
  30. resetTRX();
  31. taskSuccess('d');
  32. }
  33. else //time out when waiting for ack.
  34. {
  35. numDataRetry++;
  36. if (numDataRetry <= aMaxFrameRetries)
  37. {
  38. taskP.taskStep(task) = 1; //important
  39. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  40. waitDataAck = false;
  41. csmacaResume();
  42. }
  43. else
  44. {
  45. taskP.taskStatus(task) = false;
  46. resetTRX();
  47. taskFailed('d',m_NO_ACK);
  48. }
  49. }
  50. #ifdef SHUTDOWN
  51. if ((em) && ((!capability.FFD)||(numberDeviceLink(&deviceLink1) == 0)) && (NOW>phy->T_sleep_)){ //I can sleep only if i am not a coordinator
  52. phy->putNodeToSleep();
  53. }
  54. #endif
  55. break;
  56. default:
  57. break;
  58. }
  59. }
  60. }
  61. void Mac802_15_4::mlme_associate_request(UINT_8 LogicalChannel,UINT_8 CoordAddrMode,UINT_16 CoordPANId,IE3ADDR CoordAddress,
  62.  UINT_8 CapabilityInformation,bool SecurityEnable,
  63.  bool frUpper,PHYenum status,MACenum mStatus)
  64. {
  65. //refer to Figure 25 for association details
  66. UINT_8 step,task;
  67. FrameCtrl frmCtrl;
  68. hdr_lrwpan* wph;
  69. task = TP_mlme_associate_request;
  70. if (frUpper) checkTaskOverflow(task);
  71. step = taskP.taskStep(task);
  72. switch(step)
  73. {
  74. case 0:
  75. //check if parameters valid or not
  76. if ((!phy->channelSupported(LogicalChannel))
  77. || ((CoordAddrMode != defFrmCtrl_AddrMode16)&&(CoordAddrMode != defFrmCtrl_AddrMode64)))
  78. {
  79. sscs->MLME_ASSOCIATE_confirm(0,m_INVALID_PARAMETER);
  80. return;
  81. }
  82. //assert(mpib.macShortAddress == 0xffff); //not associated yet
  83. //we may optionally track beacons if beacon enabled (here we don't)
  84. tmp_ppib.phyCurrentChannel = LogicalChannel;
  85. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  86. mpib.macPANId = CoordPANId;
  87. mpib.macCoordExtendedAddress = CoordAddress;
  88. taskP.taskStatus(task) = true;
  89. taskP.taskStep(task)++;
  90. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  91. taskP.mlme_associate_request_CoordAddrMode = CoordAddrMode;
  92. taskP.mlme_associate_request_SecurityEnable = SecurityEnable;
  93. //--- send an association request command ---
  94. #ifdef DEBUG802_15_4
  95. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  96. #endif
  97. assert(!txBcnCmd2);
  98. txBcnCmd2 = Packet::alloc();
  99. assert(txBcnCmd2);
  100. wph = HDR_LRWPAN(txBcnCmd2);
  101. constructCommandHeader(txBcnCmd2,&frmCtrl,0x01,CoordAddrMode,CoordPANId,CoordAddress,defFrmCtrl_AddrMode64,0xffff,aExtendedAddress,SecurityEnable,false,true);
  102. wph->MSDU_Payload[0] = capability.cap;
  103. constructMPDU(2,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x01,0);
  104. csmacaBegin('C');
  105. //------------------------------------
  106. break;
  107. case 1:
  108. if (status == p_IDLE)
  109. {
  110. taskP.taskStep(task)++;
  111. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
  112. if (Mac802_15_4::verbose)
  113. fprintf(stdout,"[%f](node %d) sending association request command ...n",CURRENT_TIME,index_);
  114. plme_set_trx_state_request(p_TX_ON);
  115. break;
  116. }
  117. else
  118. {
  119. taskP.taskStatus(task) = false;
  120. freePkt(txBcnCmd2);
  121. txBcnCmd2 = 0;
  122. //restore default values
  123. mpib.macPANId = def_macPANId;
  124. mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
  125. sscs->MLME_ASSOCIATE_confirm(0,m_CHANNEL_ACCESS_FAILURE);
  126. csmacaResume();
  127. return;
  128. }
  129. break;
  130. case 2:
  131. taskP.taskStep(task)++;
  132. strcpy(taskP.taskFrFunc(task),"recvAck");
  133. plme_set_trx_state_request(p_RX_ON); //waiting for ack.
  134. txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
  135. waitBcnCmdAck2 = true;
  136. break;
  137. case 3:
  138. if (status == p_SUCCESS) //ack. received
  139. {
  140. taskP.taskStep(task)++;
  141. strcpy(taskP.taskFrFunc(task),"extractHandler");
  142. plme_set_trx_state_request(p_TRX_OFF); //we don't want to receive any packet at this moment
  143. if (Mac802_15_4::verbose)
  144. fprintf(stdout,"[%f](node %d) ack for association request command receivedn",CURRENT_TIME,index_);
  145. taskSuccess('C',false);
  146. extractT->start(aResponseWaitTime/phy->getRate('s'),false);
  147. }
  148. else //time out when waiting for ack.
  149. {
  150. numBcnCmdRetry2++;
  151. if (numBcnCmdRetry2 <= aMaxFrameRetries)
  152. {
  153. taskP.taskStep(task) = 1; //important
  154. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  155. waitBcnCmdAck2 = false;
  156. csmacaResume();
  157. }
  158. else
  159. {
  160. taskP.taskStatus(task) = false;
  161. resetTRX();
  162. freePkt(txBcnCmd2);
  163. txBcnCmd2 = 0;
  164. //restore default values
  165. mpib.macPANId = def_macPANId;
  166. mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
  167. sscs->MLME_ASSOCIATE_confirm(0,m_NO_ACK);
  168. csmacaResume();
  169. return;
  170. }
  171. }
  172. break;
  173. case 4:
  174. taskP.taskStep(task)++;
  175. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
  176. //-- send a data request command to extract the response ---
  177. #ifdef DEBUG802_15_4
  178. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  179. #endif
  180. assert(!txBcnCmd2);
  181. txBcnCmd2 = Packet::alloc();
  182. assert(txBcnCmd2);
  183. wph = HDR_LRWPAN(txBcnCmd2);
  184. if ((mpib.macShortAddress == 0xfffe)||(mpib.macShortAddress == 0xffff))
  185. {
  186. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode64);
  187. wph->MHR_SrcAddrInfo.addr_64 = aExtendedAddress;
  188. }
  189. else
  190. {
  191. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode16);
  192. wph->MHR_SrcAddrInfo.addr_16 = mpib.macShortAddress;
  193. }
  194. constructCommandHeader(txBcnCmd2,&frmCtrl,0x04,taskP.mlme_associate_request_CoordAddrMode,mpib.macPANId,mpib.macCoordExtendedAddress,frmCtrl.srcAddrMode,mpib.macPANId,wph->MHR_SrcAddrInfo.addr_64,SecurityEnable,false,true);
  195. constructMPDU(1,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x04,0);
  196. waitBcnCmdAck2 = false; //command packet not yet transmitted
  197. numBcnCmdRetry2 = 0;
  198. if (Mac802_15_4::verbose)
  199. fprintf(stdout,"[%f](node %d) sending data request command ...n",CURRENT_TIME,index_);
  200. txCsmaca = txBcnCmd2;
  201. plme_set_trx_state_request(p_TX_ON);
  202. //------------------------------------
  203. break;
  204. case 5:
  205. taskP.taskStep(task)++;
  206. strcpy(taskP.taskFrFunc(task),"recvAck");
  207. //enable the receiver
  208. plme_set_trx_state_request(p_RX_ON);
  209. txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
  210. waitBcnCmdAck2 = true;
  211. break;
  212. case 6:
  213. if (status == p_SUCCESS) //ack. received
  214. {
  215. taskP.taskStep(task)++;
  216. strcpy(taskP.taskFrFunc(task),"IFSHandler");
  217. plme_set_trx_state_request(p_RX_ON); //wait for response
  218. if (Mac802_15_4::verbose)
  219. fprintf(stdout,"[%f](node %d) ack for data request command receivedn",CURRENT_TIME,index_);
  220. taskSuccess('C',false);
  221. extractT->start(aResponseWaitTime/phy->getRate('s'),false); //compare: for normal data, wait for <aMaxFrameResponseTime> symbols (or CAP symbols if beacon enabled) (see page 156, line 1-3)
  222. }
  223. else //time out when waiting for ack.
  224. {
  225. //No retransmission required in general (just wait for next beacon and poll again, see page 156, line 20-24),
  226. //but we need to retransmit here, since the node will not handle the pending list before it has associated
  227. //with the coordinator.
  228. numBcnCmdRetry2++;
  229. if (numBcnCmdRetry2 <= aMaxFrameRetries)
  230. {
  231. taskP.taskStep(task) = 5; //important
  232. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
  233. waitBcnCmdAck2 = false;
  234. txCsmaca = txBcnCmd2;
  235. plme_set_trx_state_request(p_TX_ON);
  236. }
  237. else
  238. {
  239. taskP.taskStatus(task) = false;
  240. resetTRX();
  241. freePkt(txBcnCmd2);
  242. txBcnCmd2 = 0;
  243. //restore default values
  244. mpib.macPANId = def_macPANId;
  245. mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
  246. sscs->MLME_ASSOCIATE_confirm(0,m_NO_DATA); //assume no DATA
  247. csmacaResume();
  248. return;
  249. }
  250. }
  251. break;
  252. case 7:
  253. taskP.taskStatus(task) = false;
  254. resetTRX();
  255. if (status == p_SUCCESS) //response received
  256. {
  257. if (mStatus == m_SUCCESS)
  258. {
  259. changeNodeColor(CURRENT_TIME,(mpib.macAssociationPermit)?Nam802_15_4::def_Coor_clr:Nam802_15_4::def_Dev_clr);
  260. char label[31];
  261. sprintf(label,"[%d]",mpib.macCoordExtendedAddress);
  262. #ifdef ZigBeeIF
  263. if (sscs->t_isCT)
  264. sprintf(label,""%s%d (%d.%d)"",(sscs->RNType())?"+":"-",rt_myNodeID,sscs->rt_myParentNodeID,sscs->rt_myDepth);
  265. #endif
  266. nam->changeLabel(CURRENT_TIME,label);
  267. }
  268. else
  269. {
  270. //restore default values
  271. mpib.macPANId = def_macPANId;
  272. mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
  273. }
  274. //stop the timer
  275. if (Mac802_15_4::verbose)
  276. fprintf(stdout,"[%f](node %d) association response command receivedn",CURRENT_TIME,index_);
  277. extractT->stop();
  278. sscs->MLME_ASSOCIATE_confirm(rt_myNodeID,mStatus);
  279. }
  280. else //time out when waiting for response
  281. {
  282. //restore default values
  283. mpib.macPANId = def_macPANId;
  284. mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
  285. sscs->MLME_ASSOCIATE_confirm(0,m_NO_DATA);
  286. }
  287. csmacaResume();
  288. default:
  289. break;
  290. }
  291. }
  292. void Mac802_15_4::mlme_associate_response(IE3ADDR DeviceAddress,UINT_16 AssocShortAddress,MACenum Status,bool SecurityEnable,
  293.   bool frUpper,PHYenum status)
  294. {
  295. FrameCtrl frmCtrl;
  296. hdr_lrwpan* wph;
  297. Packet *rspPkt;
  298. double kpTime;
  299. UINT_8 step,task;
  300. int i;
  301. task = TP_mlme_associate_response;
  302. //checkTaskOverflow(task);
  303. if (frUpper)
  304. {
  305. if (taskP.taskStatus(task)) //overflow
  306. {
  307. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_TRANSACTION_OVERFLOW);
  308. return;
  309. }
  310. taskP.taskStep(task) = 0;
  311. (taskP.taskFrFunc(task))[0] = 0;
  312. }
  313. step = taskP.taskStep(task);
  314. switch(step)
  315. {
  316. case 0:
  317. //check if parameters valid or not
  318. if ((Status != m_SUCCESS)&&(Status != m_PAN_at_capacity)&&(Status != m_PAN_access_denied))
  319. {
  320. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_INVALID_PARAMETER);
  321. return;
  322. }
  323. taskP.taskStatus(task) = true;
  324. taskP.taskStep(task)++;
  325. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  326. taskP.mlme_associate_response_DeviceAddress = DeviceAddress;
  327. //--- construct an association response command packet and put it in the pending list ---
  328. rspPkt = Packet::alloc();
  329. assert(rspPkt);
  330. wph = HDR_LRWPAN(rspPkt);
  331. #ifdef ZigBeeIF
  332. sscs->setGetClusTreePara('s',rspPkt);
  333. #endif
  334. constructCommandHeader(rspPkt,&frmCtrl,0x02,defFrmCtrl_AddrMode64,mpib.macPANId,DeviceAddress,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,SecurityEnable,false,true);
  335. *((UINT_16 *)wph->MSDU_Payload) = AssocShortAddress;
  336. *((MACenum *)(wph->MSDU_Payload + 2)) = Status;
  337. constructMPDU(4,rspPkt,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x02,0);
  338. kpTime = (2 * aResponseWaitTime) / phy->getRate('s');
  339. i = chkAddTransacLink(&transacLink1,&transacLink2,defFrmCtrl_AddrMode64,DeviceAddress,rspPkt,0,kpTime);
  340. if (i != 0) //overflow or failed
  341. {
  342. #ifdef DEBUG802_15_4
  343. hdr_cmn *ch = HDR_CMN(rspPkt);
  344. fprintf(stdout,"[%s::%s][%f](node %d) task overflow or failed: type = %s, src = %d, dst = %d, uid = %d, mac_uid = ??, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(rspPkt),p802_15_4macSA(rspPkt),p802_15_4macDA(rspPkt),wph->uid,ch->size());
  345. #endif
  346. taskP.taskStatus(task) = false;
  347. Packet::free(rspPkt);
  348. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_TRANSACTION_OVERFLOW);
  349. return;
  350. }
  351. //----------------------------------------------------------------------
  352. assoRspWaitT->start(kpTime);
  353. taskP.mlme_associate_response_pendPkt = rspPkt;
  354. break;
  355. case 1:
  356. if (!taskP.taskStatus(task))
  357. break;
  358. taskP.taskStatus(task) = false;
  359. assoRspWaitT->stop();
  360. if (status == p_SUCCESS) //response packet transmitted and ack. received
  361. {
  362. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_SUCCESS);
  363. taskSuccess('c');
  364. }
  365. else //response packet transmission failed
  366. {
  367. //be careful, we use MACenum to return the status, either CHANNEL_ACCESS_FAILURE or NO_ACK
  368. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,Status);
  369. freePkt(txBcnCmd);
  370. txBcnCmd = 0;
  371. }
  372. break;
  373. case 2:
  374. if (!taskP.taskStatus(task))
  375. break;
  376. taskP.taskStatus(task) = false;
  377. //check if the transaction still pending -- actually no need to check (it must be pending if case 1 didn't happen), but no harm
  378. i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,taskP.mlme_associate_response_pendPkt); //don't use <txBcnCmd>, since assignment 'txBcnCmd = rspPkt' only happens if a data request command received
  379. if (i == 0) //still pending
  380. {
  381. //delete the packet from the transaction list immediately -- prevent the packet from being transmitted at the last moment
  382. updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,taskP.mlme_associate_response_pendPkt);
  383. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_TRANSACTION_EXPIRED);
  384. return;
  385. }
  386. else //being successfully extracted
  387. {
  388. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_SUCCESS);
  389. return;
  390. }
  391. break;
  392. default:
  393. break;
  394. }
  395. }
  396. void Mac802_15_4::mlme_disassociate_request(IE3ADDR DeviceAddress,UINT_8 DisassociateReason,bool SecurityEnable,bool frUpper,PHYenum status)
  397. {
  398. /*
  399. FrameCtrl frmCtrl;
  400. hdr_lrwpan* wph;
  401. double kpTime;
  402. UINT_8 step,task;
  403. int i;
  404. task = TP_mlme_disassociate_request;
  405. if (frUpper) checkTaskOverflow(task);
  406. step = taskP.taskStep(task);
  407. switch(step)
  408. {
  409. case 0:
  410. //check if parameters valid or not
  411. if (DeviceAddress != mpib.macCoordExtendedAddress) //send to a device
  412. if ((!capability.FFD)||(numberDeviceLink(&deviceLink1) == 0)) //I am not a coordinator
  413. {
  414. sscs->MLME_DISASSOCIATE_confirm(m_INVALID_PARAMETER);
  415. return;
  416. }
  417. taskP.mlme_disassociate_request_toCoor = (DeviceAddress == mpib.macCoordExtendedAddress);
  418. //--- construct a disassociation notification command packet ---
  419. #ifdef DEBUG802_15_4
  420. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  421. #endif
  422. assert(!txBcnCmd2);
  423. txBcnCmd2 = Packet::alloc();
  424. assert(txBcnCmd2);
  425. wph = HDR_LRWPAN(txBcnCmd2);
  426. if (!taskP.mlme_disassociate_request_toCoor)
  427. wph->MHR_DstAddrInfo.addr_64 = DeviceAddress;
  428. else
  429. wph->MHR_DstAddrInfo.addr_64 = mpib.macCoordExtendedAddress;
  430. constructCommandHeader(txBcnCmd2,&frmCtrl,0x03,defFrmCtrl_AddrMode64,mpib.macPANId,wph->MHR_DstAddrInfo.addr_64,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,SecurityEnable,false,true);
  431. *((UINT_8 *)wph->MSDU_Payload) = (taskP.mlme_disassociate_request_toCoor)?0x02:0x01;
  432. constructMPDU(2,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x03,0);
  433. //----------------------------------------------------------------------
  434. taskP.taskStatus(task) = true;
  435. taskP.taskStep(task)++;
  436. taskP.mlme_disassociate_request_pendPkt = txBcnCmd2;
  437. if (!taskP.mlme_disassociate_request_toCoor) //indirect transmission should be used
  438. {
  439. // Linux floating number compatibility
  440. //kpTime = mpib.macTransactionPersistenceTime * (aBaseSuperframeDuration * (1 << mpib.macBeaconOrder) / phy->getRate('s'));
  441. {
  442. double tmpf;
  443. tmpf = (aBaseSuperframeDuration * (1 << mpib.macBeaconOrder) / phy->getRate('s'));
  444. kpTime = mpib.macTransactionPersistenceTime * tmpf;
  445. }
  446. i = chkAddTransacLink(&transacLink1,&transacLink2,defFrmCtrl_AddrMode64,wph->MHR_DstAddrInfo.addr_64,txBcnCmd2,0,kpTime);
  447. if (i != 0) //overflow or failed
  448. {
  449. taskP.taskStatus(task) = false;
  450. Packet::free(txBcnCmd2);
  451. txBcnCmd2 = 0;
  452. sscs->MLME_DISASSOCIATE_confirm(m_TRANSACTION_OVERFLOW);
  453. return;
  454. }
  455. extractT->start(kpTime,false);
  456. }
  457. else
  458. csmacaBegin('C');
  459. break;
  460. case 1:
  461. if (!taskP.mlme_disassociate_request_toCoor) //indirect transmission
  462. {
  463. //check if the transaction still pending
  464. wph = HDR_LRWPAN(txBcnCmd2);
  465. i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,taskP.mlme_disassociate_request_pendPkt); //don't use <txBcnCmd2>, since it may be null if a data request command not received
  466. if (i == 0) //still pending
  467. {
  468. //delete the packet from the transaction list immediately -- prevent the packet from being transmitted at the last moment
  469. updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,taskP.mlme_disassociate_request_pendPkt);
  470. taskP.taskStatus(task) = false;
  471. sscs->MLME_DISASSOCIATE_confirm(m_TRANSACTION_EXPIRED);
  472. return;
  473. }
  474. else //being successfully extracted
  475. {
  476. taskP.taskStatus(task) = false;
  477. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_SUCCESS);
  478. return;
  479. }
  480. }
  481. else
  482. {
  483. }
  484. break;
  485. default:
  486. break;
  487. }
  488. */
  489. }
  490. void Mac802_15_4::mlme_orphan_response(IE3ADDR OrphanAddress,UINT_16 ShortAddress,bool AssociatedMember,bool SecurityEnable,bool frUpper,PHYenum status)
  491. {
  492. hdr_lrwpan* wph;
  493. FrameCtrl frmCtrl;
  494. //UINT_8 step;
  495. UINT_8 task;
  496. task = TP_mlme_orphan_response;
  497. if (frUpper) checkTaskOverflow(task);
  498. switch(taskP.taskStep(task))
  499. {
  500. case 0:
  501. if (AssociatedMember)
  502. {
  503. //send a coordinator realignment command
  504. #ifdef DEBUG802_15_4
  505. 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);
  506. #endif
  507. taskP.taskStatus(task) = true;
  508. taskP.taskStep(task)++;
  509. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  510. taskP.mlme_orphan_response_OrphanAddress = OrphanAddress;
  511. assert(!txBcnCmd);
  512. txBcnCmd = Packet::alloc();
  513. assert(txBcnCmd);
  514. wph = HDR_LRWPAN(txBcnCmd);
  515. constructCommandHeader(txBcnCmd,&frmCtrl,0x08,defFrmCtrl_AddrMode64,0xffff,OrphanAddress,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,SecurityEnable,false,true);
  516. *((UINT_16 *)wph->MSDU_Payload) = mpib.macPANId;
  517. *((UINT_16 *)wph->MSDU_Payload + 2) = mpib.macShortAddress;
  518. phy->PLME_GET_request(phyCurrentChannel);
  519. *((UINT_8 *)wph->MSDU_Payload + 4) = tmp_ppib.phyCurrentChannel;
  520. *((UINT_16 *)wph->MSDU_Payload + 5) = ShortAddress;
  521. constructMPDU(8,txBcnCmd,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x08,0);
  522. csmacaBegin('c');
  523. }
  524. break;
  525. case 1:
  526. taskP.taskStatus(task) = false;
  527. if (status == p_SUCCESS) //response packet transmitted and ack. received
  528. {
  529. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,OrphanAddress,m_SUCCESS);
  530. taskSuccess('c');
  531. }
  532. else //response packet transmission failed
  533. {
  534. sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,OrphanAddress,m_CHANNEL_ACCESS_FAILURE);
  535. freePkt(txBcnCmd);
  536. txBcnCmd = 0;
  537. csmacaResume(); //other packets may be waiting
  538. }
  539. break;
  540. default:
  541. break;
  542. }
  543. }
  544. void Mac802_15_4::mlme_reset_request(bool SetDefaultPIB,bool frUpper,PHYenum status)
  545. {
  546. //UINT_8 step;
  547. UINT_8 task;
  548. task = TP_mlme_reset_request;
  549. if (frUpper) checkTaskOverflow(task);
  550. switch(taskP.taskStep(task))
  551. {
  552. case 0:
  553. taskP.taskStatus(task) = true;
  554. taskP.taskStep(task)++;
  555. strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
  556. taskP.mlme_reset_request_SetDefaultPIB = SetDefaultPIB;
  557. {plme_set_trx_state_request(p_TRX_OFF);}
  558. break;
  559. case 1:
  560. taskP.taskStatus(task) = false;
  561. init(true);
  562. if (SetDefaultPIB)
  563. mpib = MPIB;
  564. if (status == p_TRX_OFF)
  565. sscs->MLME_RESET_confirm(m_SUCCESS);
  566. else
  567. sscs->MLME_RESET_confirm(m_DISABLE_TRX_FAILURE);
  568. break;
  569. default:
  570. break;
  571. }
  572. }
  573. void Mac802_15_4::mlme_rx_enable_request(bool DeferPermit,UINT_32 RxOnTime,UINT_32 RxOnDuration,bool frUpper,PHYenum status)
  574. {
  575. UINT_8 step,task;
  576. UINT_32 t_CAP;
  577. double cutTime,tmpf;
  578. task = TP_mlme_rx_enable_request;
  579. if (frUpper) checkTaskOverflow(task);
  580. step = taskP.taskStep(task);
  581. if (step == 0)
  582. if (RxOnDuration == 0)
  583. {
  584. sscs->MLME_RX_ENABLE_confirm(m_SUCCESS);
  585. plme_set_trx_state_request(p_TRX_OFF);
  586. return;
  587. }
  588. if (macBeaconOrder2 != 15) //beacon enabled
  589. {
  590. switch(step)
  591. {
  592. case 0:
  593. taskP.mlme_rx_enable_request_RxOnTime = RxOnTime;
  594. taskP.mlme_rx_enable_request_RxOnDuration = RxOnDuration;
  595. if (RxOnTime + RxOnDuration >= sfSpec2.BI)
  596. {
  597. sscs->MLME_RX_ENABLE_confirm(m_INVALID_PARAMETER);
  598. return;
  599. }
  600. t_CAP = (sfSpec2.FinCAP + 1) * sfSpec2.sd;
  601. /* Linux floating number compatibility
  602. */
  603. tmpf = CURRENT_TIME * phy->getRate('s');
  604. if ((RxOnTime - aTurnaroundTime) > t_CAP)
  605. {
  606. sscs->MLME_RX_ENABLE_confirm(m_OUT_OF_CAP);
  607. return;
  608. }
  609. /* Linux floating number compatibility
  610. else if ((CURRENT_TIME * phy->getRate('s') - macBcnRxTime) < (RxOnTime - aTurnaroundTime))
  611. */
  612. else if ((tmpf - macBcnRxTime) < (RxOnTime - aTurnaroundTime))
  613. {
  614. //can proceed in current superframe
  615. taskP.taskStatus(task) = true;
  616. taskP.taskStep(task)++;
  617. //just fall through case 1
  618. }
  619. else if (DeferPermit)
  620. {
  621. //need to defer until next superframe
  622. taskP.taskStatus(task) = true;
  623. taskP.taskStep(task)++;
  624. strcpy(taskP.taskFrFunc(task),"recvBeacon");
  625. break;
  626. }
  627. else
  628. {
  629. sscs->MLME_RX_ENABLE_confirm(m_OUT_OF_CAP);
  630. return;
  631. }
  632. case 1:
  633. taskP.taskStep(task)++;
  634. strcpy(taskP.taskFrFunc(task),"rxEnableHandler");
  635. /* Linux floating number compatibility
  636. rxEnableT->start(RxOnTime / phy->getRate('s') - (CURRENT_TIME - macBcnRxTime / phy->getRate('s')));
  637. */
  638. {
  639. double tmpf2;
  640. tmpf = macBcnRxTime / phy->getRate('s');
  641. tmpf = CURRENT_TIME - tmpf;
  642. tmpf2 = RxOnTime / phy->getRate('s');
  643. tmpf = tmpf2 - tmpf;
  644. rxEnableT->start(tmpf);
  645. }
  646. break;
  647. case 2:
  648. taskP.taskStep(task)++;
  649. strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
  650. taskP.mlme_rx_enable_request_currentTime = CURRENT_TIME;
  651. plme_set_trx_state_request(p_RX_ON);
  652. break;
  653. case 3:
  654. taskP.taskStatus(task) = false;
  655. strcpy(taskP.taskFrFunc(task),"rxEnableHandler");
  656. taskP.taskStep(task)++;
  657. if (status == p_TX_ON)
  658. sscs->MLME_RX_ENABLE_confirm(m_TX_ACTIVE);
  659. else
  660. sscs->MLME_RX_ENABLE_confirm(m_SUCCESS);
  661. //turn off the receiver before the CFP so as not to disturb it, and we see no reason to turn it on again after the CFP (i.e., inactive port of the superframe)
  662. t_CAP = (sfSpec2.FinCAP + 1) * sfSpec2.sd;
  663. cutTime = (RxOnTime + RxOnDuration - t_CAP) / phy->getRate('s');
  664. /* Linux floating number compatibility
  665. rxEnableT->start(RxOnDuration / phy->getRate('s') - (CURRENT_TIME - taskP.mlme_rx_enable_request_currentTime) - cutTime);
  666. */
  667. {
  668. tmpf = RxOnDuration / phy->getRate('s');
  669. tmpf -= CURRENT_TIME;
  670. tmpf += taskP.mlme_rx_enable_request_currentTime;
  671. tmpf -= cutTime;
  672. rxEnableT->start(tmpf);
  673. }
  674. break;
  675. case 4:
  676. strcpy(taskP.taskFrFunc(task),"");
  677. plme_set_trx_state_request(p_TRX_OFF);
  678. break;
  679. default:
  680. break;
  681. }
  682. }
  683. else
  684. {
  685. switch(step)
  686. {
  687. case 0:
  688. taskP.taskStatus(task) = true;
  689. strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
  690. taskP.taskStep(task)++;
  691. taskP.mlme_rx_enable_request_RxOnDuration = RxOnDuration;
  692. taskP.mlme_rx_enable_request_currentTime = CURRENT_TIME;
  693. plme_set_trx_state_request(p_RX_ON);
  694. break;
  695. case 1:
  696. taskP.taskStatus(task) = false;
  697. strcpy(taskP.taskFrFunc(task),"rxEnableHandler");
  698. taskP.taskStep(task)++;
  699. if (status == p_TX_ON)
  700. sscs->MLME_RX_ENABLE_confirm(m_TX_ACTIVE);
  701. else
  702. sscs->MLME_RX_ENABLE_confirm(m_SUCCESS);
  703. /* Linux floating number compatibility
  704. rxEnableT->start(RxOnDuration / phy->getRate('s') - (CURRENT_TIME - taskP.mlme_rx_enable_request_currentTime));
  705. */
  706. {
  707. tmpf = RxOnDuration / phy->getRate('s');
  708. tmpf -= CURRENT_TIME;
  709. tmpf += taskP.mlme_rx_enable_request_currentTime;
  710. rxEnableT->start(tmpf);
  711. }
  712. break;
  713. case 2:
  714. strcpy(taskP.taskFrFunc(task),"");
  715. plme_set_trx_state_request(p_TRX_OFF);
  716. break;
  717. default:
  718. break;
  719. }
  720. }
  721. }
  722. void Mac802_15_4::mlme_scan_request(UINT_8 ScanType,UINT_32 ScanChannels,UINT_8 ScanDuration,bool frUpper,PHYenum status)
  723. {
  724. UINT_32 t_chanPos;
  725. UINT_8 step,task;
  726. FrameCtrl frmCtrl;
  727. hdr_lrwpan* wph;
  728. int i;
  729. task = TP_mlme_scan_request;
  730. if (frUpper) checkTaskOverflow(task);
  731. step = taskP.taskStep(task);
  732. if (step == 0)
  733. {
  734. if ((ScanType > 3)
  735. ||((ScanType != 3)&&(ScanDuration > 14)))
  736. {
  737. sscs->MLME_SCAN_confirm(m_INVALID_PARAMETER,ScanType,ScanChannels,0,NULL,NULL);
  738. return;
  739. }
  740. //disable the beacon
  741. taskP.mlme_scan_request_orig_macBeaconOrder = mpib.macBeaconOrder;
  742. taskP.mlme_scan_request_orig_macBeaconOrder2 = macBeaconOrder2;
  743. taskP.mlme_scan_request_orig_macBeaconOrder3 = macBeaconOrder3;
  744. mpib.macBeaconOrder = 15;
  745. macBeaconOrder2 = 15;
  746. macBeaconOrder3 = 15;
  747. //stop the CSMA-CA if it is running
  748. if (backoffStatus == 99)
  749. {
  750. backoffStatus = 0;
  751. csmaca->cancel();
  752. }
  753. taskP.mlme_scan_request_ScanType = ScanType;
  754. }
  755. if (ScanType == 0x00) //ED scan
  756. switch (step)
  757. {
  758. case 0:
  759. phy->PLME_GET_request(phyChannelsSupported); //value will be returned in tmp_ppib
  760. taskP.mlme_scan_request_ScanChannels = ScanChannels;
  761. if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
  762. {
  763. //restore the beacon order
  764. mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
  765. macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
  766. macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
  767. sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,ScanChannels,0,NULL,NULL); //SUCCESS or INVALID_PARAMETER?
  768. csmacaResume();
  769. return;
  770. }
  771. taskP.taskStatus(task) = true;
  772. taskP.taskStep(task)++;
  773. strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
  774. taskP.mlme_scan_request_CurrentChannel = 0;
  775. taskP.mlme_scan_request_ListNum = 0;
  776. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  777. while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
  778. ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
  779. {
  780. taskP.mlme_scan_request_CurrentChannel++;
  781. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  782. }
  783. tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
  784. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  785. break;
  786. case 1:
  787. taskP.taskStep(task)++;
  788. strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
  789. {plme_set_trx_state_request(p_RX_ON);}
  790. break;
  791. case 2:
  792. if (status == p_RX_ON)
  793. {
  794. taskP.taskStep(task)++;
  795. strcpy(taskP.taskFrFunc(task),"PLME_ED_confirm");
  796. phy->PLME_ED_request();
  797. break;
  798. }
  799. //else //fall through case 4
  800. case 3:
  801. if (step == 3) //note that case 2 needs to fall through case 4 via here
  802. {
  803. if (status == p_SUCCESS)
  804. {
  805. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  806. taskP.mlme_scan_request_ScanChannels &= (t_chanPos^0xffffffff);
  807. taskP.mlme_scan_request_EnergyDetectList[taskP.mlme_scan_request_ListNum] = energyLevel;
  808. taskP.mlme_scan_request_ListNum++;
  809. }
  810. }
  811. //fall through
  812. case 4:
  813. if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
  814. {
  815. //restore the beacon order
  816. mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
  817. macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
  818. macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
  819. taskP.taskStatus(task) = false;
  820. sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ListNum,taskP.mlme_scan_request_EnergyDetectList,NULL);
  821. csmacaResume();
  822. return;
  823. }
  824. taskP.taskStep(task) = 1; //important
  825. strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
  826. taskP.mlme_scan_request_CurrentChannel++;
  827. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  828. while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
  829. ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
  830. {
  831. taskP.mlme_scan_request_CurrentChannel++;
  832. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  833. }
  834. tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
  835. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  836. break;
  837. default:
  838. break;
  839. }
  840. else if ((ScanType == 0x01) //active scan
  841. ||  (ScanType == 0x02)) //passive scan
  842. switch (step)
  843. {
  844. case 0:
  845. phy->PLME_GET_request(phyChannelsSupported); //value will be returned in tmp_ppib
  846. taskP.mlme_scan_request_ScanChannels = ScanChannels;
  847. if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
  848. {
  849. mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
  850. macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
  851. macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
  852. sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,ScanChannels,0,NULL,NULL); //SUCCESS or INVALID_PARAMETER?
  853. csmacaResume();
  854. return;
  855. }
  856. taskP.taskStatus(task) = true;
  857. taskP.taskStep(task)++;
  858. strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
  859. taskP.mlme_scan_request_orig_macPANId = mpib.macPANId;
  860. mpib.macPANId = 0xffff;
  861. taskP.mlme_scan_request_ScanDuration = ScanDuration;
  862. taskP.mlme_scan_request_CurrentChannel = 0;
  863. taskP.mlme_scan_request_ListNum = 0;
  864. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  865. while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
  866. ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
  867. {
  868. taskP.mlme_scan_request_CurrentChannel++;
  869. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  870. }
  871. tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
  872. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  873. break;
  874. case 1:
  875. if (Mac802_15_4::verbose)
  876. fprintf(stdout,"[%f](node %d) scanning channel %dn",CURRENT_TIME,index_,taskP.mlme_scan_request_CurrentChannel);
  877. if (ScanType == 0x01) //active scan
  878. {
  879. taskP.taskStep(task)++;
  880. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  881. //--- send a beacon request command ---
  882. #ifdef DEBUG802_15_4
  883. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  884. #endif
  885. assert(!txBcnCmd2);
  886. txBcnCmd2 = Packet::alloc();
  887. assert(txBcnCmd2);
  888. wph = HDR_LRWPAN(txBcnCmd2);
  889. constructCommandHeader(txBcnCmd2,&frmCtrl,0x07,defFrmCtrl_AddrMode16,0xffff,0xffff,defFrmCtrl_AddrModeNone,0,0,false,false,false);
  890. constructMPDU(1,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x07,0);
  891. csmacaBegin('C');
  892. //------------------------------------
  893. }
  894. else
  895. {
  896. taskP.taskStep(task) = 4; //skip the steps only for active scan
  897. strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
  898. plme_set_trx_state_request(p_RX_ON);
  899. }
  900. break;
  901. case 2:
  902. if (status == p_IDLE)
  903. {
  904. taskP.taskStep(task)++;
  905. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
  906. plme_set_trx_state_request(p_TX_ON);
  907. break;
  908. }
  909. else
  910. {
  911. freePkt(txBcnCmd2); //actually we can keep <txBcnCmd2> for next channel
  912. txBcnCmd2 = 0;
  913. //fall through case 7
  914. }
  915. case 3:
  916. if (step == 3)
  917. {
  918. taskP.taskStep(task)++;
  919. strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
  920. taskSuccess('C',false);
  921. plme_set_trx_state_request(p_RX_ON);
  922. break;
  923. }
  924. case 4:
  925. if (step == 4)
  926. {
  927. if (status == p_RX_ON)
  928. {
  929. taskP.taskStep(task)++;
  930. strcpy(taskP.taskFrFunc(task),"recvBeacon");
  931. //schedule for next channel
  932. scanT->start((aBaseSuperframeDuration * ((1 << taskP.mlme_scan_request_ScanDuration) + 1)) / phy->getRate('s'));
  933. break;
  934. }
  935. //else //fall through case 7
  936. }
  937. case 5:
  938. if (step == 5)
  939. {
  940. //beacon received
  941. //record the PAN descriptor if it is a new one
  942. assert(rxBeacon);
  943. wph = HDR_LRWPAN(rxBeacon);
  944. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  945. frmCtrl.parse();
  946. for (i=0;i<taskP.mlme_scan_request_ListNum;i++)
  947. if ((taskP.mlme_scan_request_PANDescriptorList[i].LogicalChannel == taskP.mlme_scan_request_CurrentChannel)
  948. && (taskP.mlme_scan_request_PANDescriptorList[i].CoordAddrMode == frmCtrl.srcAddrMode)
  949. && (taskP.mlme_scan_request_PANDescriptorList[i].CoordPANId == wph->MHR_SrcAddrInfo.panID) //but (page 146, line 4-5) implies not checking PAN ID
  950. && (((frmCtrl.srcAddrMode == defFrmCtrl_AddrMode16)&&(taskP.mlme_scan_request_PANDescriptorList[i].CoordAddress_16 == (wph->MHR_SrcAddrInfo.addr_16))
  951. ||((frmCtrl.srcAddrMode == defFrmCtrl_AddrMode64)&&(taskP.mlme_scan_request_PANDescriptorList[i].CoordAddress_64 == wph->MHR_SrcAddrInfo.addr_64)))))
  952.   break;
  953. if (i >= taskP.mlme_scan_request_ListNum) //unique beacon
  954. {
  955. taskP.mlme_scan_request_PANDescriptorList[taskP.mlme_scan_request_ListNum] = panDes2;
  956. taskP.mlme_scan_request_ListNum++;
  957. if (taskP.mlme_scan_request_ListNum >= 27)
  958. {
  959. //stop the timer
  960. scanT->stop();
  961. //fall through case 7
  962. }
  963. else
  964. break;
  965. }
  966. else
  967. break;
  968. }
  969. case 6:
  970. if (step == 6)
  971. {
  972. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  973. taskP.mlme_scan_request_ScanChannels &= (t_chanPos^0xffffffff);
  974. //fall through case 7
  975. }
  976. case 7:
  977. if (((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
  978.    ||(taskP.mlme_scan_request_ListNum >= 27))
  979. {
  980. mpib.macPANId = taskP.mlme_scan_request_orig_macPANId;
  981. mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
  982. macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
  983. macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
  984. taskP.taskStatus(task) = false;
  985. sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ListNum,NULL,taskP.mlme_scan_request_PANDescriptorList);
  986. csmacaResume();
  987. return;
  988. }
  989. taskP.taskStep(task) = 1; //important
  990. strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
  991. taskP.mlme_scan_request_CurrentChannel++;
  992. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  993. while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
  994. ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
  995. {
  996. taskP.mlme_scan_request_CurrentChannel++;
  997. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  998. }
  999. tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
  1000. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  1001. break;
  1002. default:
  1003. break;
  1004. }
  1005. else //if (ScanType == 0x03) //orphan scan
  1006. switch (step)
  1007. {
  1008. case 0:
  1009. phy->PLME_GET_request(phyChannelsSupported); //value will be returned in tmp_ppib
  1010. taskP.mlme_scan_request_ScanChannels = ScanChannels;
  1011. if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
  1012. {
  1013. mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
  1014. //macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
  1015. macBeaconOrder2 = 15;
  1016. macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
  1017. sscs->MLME_SCAN_confirm(m_INVALID_PARAMETER,ScanType,ScanChannels,0,NULL,NULL);
  1018. csmacaResume();
  1019. return;
  1020. }
  1021. taskP.taskStatus(task) = true;
  1022. taskP.taskStep(task)++;
  1023. strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
  1024. taskP.mlme_scan_request_CurrentChannel = 0;
  1025. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  1026. while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
  1027. ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
  1028. {
  1029. taskP.mlme_scan_request_CurrentChannel++;
  1030. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  1031. }
  1032. tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
  1033. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  1034. break;
  1035. case 1:
  1036. if (Mac802_15_4::verbose)
  1037. fprintf(stdout,"[%f](node %d) orphan-scanning channel %dn",CURRENT_TIME,index_,taskP.mlme_scan_request_CurrentChannel);
  1038. taskP.taskStep(task)++;
  1039. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  1040. //--- send an orphan notification command ---
  1041. #ifdef DEBUG802_15_4
  1042. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  1043. #endif
  1044. assert(!txBcnCmd2);
  1045. txBcnCmd2 = Packet::alloc();
  1046. assert(txBcnCmd2);
  1047. wph = HDR_LRWPAN(txBcnCmd2);
  1048. constructCommandHeader(txBcnCmd2,&frmCtrl,0x06,defFrmCtrl_AddrMode64,mpib.macPANId,mpib.macCoordExtendedAddress,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,false,false,false);
  1049. constructMPDU(1,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x06,0);
  1050. csmacaBegin('C');
  1051. //------------------------------------
  1052. break;
  1053. case 2:
  1054. if (status == p_IDLE)
  1055. {
  1056. taskP.taskStep(task)++;
  1057. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
  1058. plme_set_trx_state_request(p_TX_ON);
  1059. break;
  1060. }
  1061. else
  1062. {
  1063. freePkt(txBcnCmd2);
  1064. txBcnCmd2 = 0;
  1065. //fall through case 6
  1066. }
  1067. case 3:
  1068. if (step == 3)
  1069. {
  1070. taskP.taskStep(task)++;
  1071. strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
  1072. taskSuccess('C',false);
  1073. plme_set_trx_state_request(p_RX_ON);
  1074. break;
  1075. }
  1076. case 4:
  1077. if (step == 4)
  1078. {
  1079. if (status == p_RX_ON)
  1080. {
  1081. taskP.taskStep(task)++;
  1082. strcpy(taskP.taskFrFunc(task),"IFSHandler");
  1083. scanT->start(aResponseWaitTime / phy->getRate('s'));
  1084. break;
  1085. }
  1086. //else //fall through case 6
  1087. }
  1088. case 5:
  1089. if (step == 5)
  1090. {
  1091. if (status == p_SUCCESS) //coordinator realignment command received
  1092. {
  1093. scanT->stop();
  1094. mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
  1095. macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
  1096. macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
  1097. taskP.taskStatus(task) = false;
  1098. changeNodeColor(CURRENT_TIME,(mpib.macAssociationPermit)?Nam802_15_4::def_Coor_clr:Nam802_15_4::def_Dev_clr);
  1099. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  1100. taskP.mlme_scan_request_ScanChannels &= (t_chanPos^0xffffffff);
  1101. sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,taskP.mlme_scan_request_ScanChannels,0,NULL,NULL);
  1102. csmacaResume();
  1103. break;
  1104. }
  1105. else //time out
  1106. {
  1107. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  1108. taskP.mlme_scan_request_ScanChannels &= (t_chanPos^0xffffffff);
  1109. //fall through case 6
  1110. }
  1111. }
  1112. case 6:
  1113. if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
  1114. {
  1115. mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
  1116. //macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
  1117. macBeaconOrder2 = 15;
  1118. macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
  1119. taskP.taskStatus(task) = false;
  1120. sscs->MLME_SCAN_confirm(m_NO_BEACON,ScanType,taskP.mlme_scan_request_ScanChannels,0,NULL,NULL);
  1121. csmacaResume();
  1122. return;
  1123. }
  1124. taskP.taskStep(task) = 1; //important
  1125. strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
  1126. taskP.mlme_scan_request_CurrentChannel++;
  1127. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  1128. while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
  1129. ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
  1130. {
  1131. taskP.mlme_scan_request_CurrentChannel++;
  1132. t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
  1133. }
  1134. tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
  1135. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  1136. break;
  1137. default:
  1138. break;
  1139. }
  1140. }
  1141. void Mac802_15_4::mlme_start_request(UINT_16 PANId,UINT_8 LogicalChannel,UINT_8 BeaconOrder,
  1142.      UINT_8 SuperframeOrder,bool PANCoordinator,bool BatteryLifeExtension,
  1143.      bool CoordRealignment,bool SecurityEnable,
  1144.      bool frUpper,PHYenum status)
  1145. {
  1146. FrameCtrl frmCtrl;
  1147. hdr_lrwpan* wph;
  1148. UINT_8 origBeaconOrder;
  1149. UINT_8 step,task;
  1150. task = TP_mlme_start_request;
  1151. if (frUpper) checkTaskOverflow(task);
  1152. step = taskP.taskStep(task);
  1153. switch (step)
  1154. {
  1155. case 0:
  1156. if (mpib.macShortAddress == 0xffff)
  1157. {
  1158. sscs->MLME_START_confirm(m_NO_SHORT_ADDRESS);
  1159. return;
  1160. }
  1161. else if ((!phy->channelSupported(LogicalChannel))
  1162. || (BeaconOrder > 15)
  1163. || ((SuperframeOrder > BeaconOrder)&&(SuperframeOrder != 15)))
  1164. {
  1165. sscs->MLME_START_confirm(m_INVALID_PARAMETER);
  1166. return;
  1167. }
  1168. else if (!capability.FFD)
  1169. {
  1170. sscs->MLME_START_confirm(m_UNDEFINED);
  1171. return;
  1172. }
  1173. taskP.taskStatus(task) = true;
  1174. if (CoordRealignment) //send a realignment command before changing configuration that affects the command
  1175. {
  1176. taskP.taskStep(task)++;
  1177. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  1178. //broadcast a realignment command
  1179. #ifdef DEBUG802_15_4
  1180. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  1181. #endif
  1182. assert(!txBcnCmd2);
  1183. txBcnCmd2 = Packet::alloc();
  1184. assert(txBcnCmd2);
  1185. wph = HDR_LRWPAN(txBcnCmd2);
  1186. constructCommandHeader(txBcnCmd2,&frmCtrl,0x08,defFrmCtrl_AddrMode16,0xffff,0xffff,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,false,false,false);
  1187. //--- payload (refer to Figure 56) ---
  1188. wph->MSDU_PayloadLen = 7;
  1189. *((UINT_16 *)wph->MSDU_Payload) = PANId; //PAN identifier
  1190. *((UINT_16 *)(wph->MSDU_Payload + 2)) = mpib.macShortAddress; //Coor. short address
  1191. wph->MSDU_Payload[4] = LogicalChannel; //Logical channel
  1192. *((UINT_16 *)(wph->MSDU_Payload + 5)) = 0xffff; //short address; be the assigned address if directed to an orphaned device
  1193. constructMPDU(8,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x08,0);
  1194. csmacaBegin('C');
  1195. //------------------------------------
  1196. //change the configuration and begin to transmit beacons after the transmission of the realignment command
  1197. taskP.mlme_start_request_BeaconOrder = BeaconOrder;
  1198. taskP.mlme_start_request_SuperframeOrder = SuperframeOrder;
  1199. taskP.mlme_start_request_BatteryLifeExtension = BatteryLifeExtension;
  1200. taskP.mlme_start_request_SecurityEnable = SecurityEnable;
  1201. taskP.mlme_start_request_PANCoordinator = PANCoordinator;
  1202. taskP.mlme_start_request_PANId = PANId;
  1203. taskP.mlme_start_request_LogicalChannel = LogicalChannel;
  1204. break;
  1205. }
  1206. else
  1207. {
  1208. taskP.taskStep(task) = 2;
  1209. step = 2;
  1210. //fall through case 2
  1211. }
  1212. case 1:
  1213. if (step == 1)
  1214. {
  1215. if (status == p_IDLE)
  1216. {
  1217. taskP.taskStep(task)++;
  1218. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
  1219. plme_set_trx_state_request(p_TX_ON);
  1220. break;
  1221. }
  1222. else
  1223. {
  1224. freePkt(txBcnCmd2); //actually we can keep <txBcnCmd2> for next channel
  1225. txBcnCmd2 = 0;
  1226. //fall through case case 2 -- ignore the failure and continue to transmit beacons
  1227. taskP.taskStep(task) = 2;
  1228. }
  1229. }
  1230. case 2:
  1231. taskP.taskStep(task)++;
  1232. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm"); //for beacon
  1233. resetTRX();
  1234. if (CoordRealignment)
  1235. taskSuccess('C',false);
  1236. //change the configuration
  1237. origBeaconOrder = mpib.macBeaconOrder;
  1238. mpib.macBeaconOrder = BeaconOrder;
  1239. if (BeaconOrder == 15)
  1240. mpib.macSuperframeOrder = 15;
  1241. else
  1242. mpib.macSuperframeOrder = SuperframeOrder;
  1243. mpib.macBattLifeExt = BatteryLifeExtension;
  1244. secuBeacon = SecurityEnable;
  1245. if (isPANCoor != PANCoordinator)
  1246. changeNodeColor(CURRENT_TIME,PANCoordinator?Nam802_15_4::def_PANCoor_clr:Nam802_15_4::def_Coor_clr);
  1247. isPANCoor = PANCoordinator;
  1248. if (PANCoordinator)
  1249. {
  1250. mpib.macPANId = PANId;
  1251. mpib.macCoordExtendedAddress = aExtendedAddress; //I'm the coordinator of myself
  1252. tmp_ppib.phyCurrentChannel = LogicalChannel;
  1253. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  1254. }
  1255. if (origBeaconOrder == BeaconOrder)
  1256. {
  1257. taskP.taskStatus(task) = false;
  1258. sscs->MLME_START_confirm(m_SUCCESS);
  1259. csmacaResume();
  1260. }
  1261. else if ((origBeaconOrder == 15)&&(BeaconOrder < 15))
  1262. {
  1263. //transmit beacon immediately
  1264. if (bcnTxT->busy()) //the timer may still be looping there
  1265. bcnTxT->stop();
  1266. bcnTxT->start(true,true,0.0);
  1267. }
  1268. else if ((origBeaconOrder < 15)&&(BeaconOrder == 15))
  1269. oneMoreBeacon = true;
  1270. break;
  1271. case 3:
  1272. taskP.taskStatus(task) = false;
  1273. sscs->MLME_START_confirm(m_SUCCESS);
  1274. taskSuccess('b');
  1275. break;
  1276. default:
  1277. break;
  1278. }
  1279. }
  1280. void Mac802_15_4::mlme_sync_request(UINT_8 LogicalChannel, bool TrackBeacon,bool frUpper,PHYenum status)
  1281. {
  1282. UINT_8 step,task,BO;
  1283. task = TP_mlme_sync_request;
  1284. if (frUpper)
  1285. {
  1286. //checkTaskOverflow(task); //overlapping allowed
  1287. //stop the beacon receiving timer if it is running
  1288. if (bcnRxT->busy())
  1289. bcnRxT->stop();
  1290. taskP.taskStep(task) = 0;
  1291. (taskP.taskFrFunc(task))[0] = 0;
  1292. }
  1293. step = taskP.taskStep(task);
  1294. switch(step)
  1295. {
  1296. case 0:
  1297. //no validation check required in the draft, but it's better to check it
  1298. if ((!phy->channelSupported(LogicalChannel)) //channel not supported
  1299.  || (mpib.macPANId == 0xffff) //broadcast PAN ID
  1300.  //|| (macBeaconOrder2 == 15) //non-beacon mode or <macBeaconOrder2> not yet populated
  1301.  )
  1302. {
  1303. sscs->MLME_SYNC_LOSS_indication(m_UNDEFINED);
  1304. return;
  1305. }
  1306. taskP.taskStatus(task) = true;
  1307. taskP.taskStep(task)++;
  1308. strcpy(taskP.taskFrFunc(task),"recvBeacon");
  1309. taskP.mlme_sync_request_numSearchRetry = 0;
  1310. taskP.mlme_sync_request_tracking = TrackBeacon;
  1311. //set current channel
  1312. tmp_ppib.phyCurrentChannel = LogicalChannel;
  1313. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  1314. //enable the receiver
  1315. {plme_set_trx_state_request(p_RX_ON);}
  1316. BO = (macBeaconOrder2 == 15)?14:macBeaconOrder2;
  1317. if (bcnSearchT->busy())
  1318. bcnSearchT->stop();
  1319. bcnSearchT->start(aBaseSuperframeDuration*((1 << BO)+1) / phy->getRate('s'));
  1320. break;
  1321. case 1:
  1322. if (status == p_SUCCESS) //beacon received
  1323. {
  1324. //no confirm primitive for the success - it's better to have one
  1325. taskP.taskStatus(task) = false;
  1326. //continue to track the beacon if required
  1327. if (TrackBeacon)
  1328. {
  1329. //reset <numSearchRetry> (so that tracking can work properly)
  1330. taskP.mlme_sync_request_numSearchRetry = 0;
  1331. if(!bcnRxT->busy())
  1332. bcnRxT->start();
  1333. }
  1334. csmacaResume();
  1335. }
  1336. else //time out when waiting for beacon
  1337. {
  1338. taskP.mlme_sync_request_numSearchRetry++;
  1339. if (taskP.mlme_sync_request_numSearchRetry <= aMaxLostBeacons)
  1340. {
  1341. plme_set_trx_state_request(p_RX_ON);
  1342. BO = (macBeaconOrder2 == 15)?14:macBeaconOrder2;
  1343. bcnSearchT->start(aBaseSuperframeDuration*((1 << BO)+1) / phy->getRate('s'));
  1344. }
  1345. else
  1346. {
  1347. taskP.taskStatus(task) = false;
  1348. changeNodeColor(CURRENT_TIME,Nam802_15_4::def_Node_clr);
  1349. sscs->MLME_SYNC_LOSS_indication(m_BEACON_LOSS);
  1350. /*If the initial beacon location fails, no need to track the beacon even it is required
  1351.  *Note that not tracking does not mean the device will not be able to receive beacons --
  1352.  *but the reception may be not so reliable since there is no synchronization.
  1353.  */
  1354. taskP.mlme_sync_request_tracking = false;
  1355. csmacaResume();
  1356. return;
  1357. }
  1358. }
  1359. break;
  1360. default:
  1361. break;
  1362. }
  1363. }
  1364. void Mac802_15_4::mlme_poll_request(UINT_8 CoordAddrMode,UINT_16 CoordPANId,IE3ADDR CoordAddress,bool SecurityEnable,
  1365.     bool autoRequest,bool firstTime,PHYenum status)
  1366. {
  1367. UINT_8 step,task;
  1368. FrameCtrl frmCtrl;
  1369. hdr_lrwpan* wph;
  1370. task = TP_mlme_poll_request;
  1371. if (firstTime)
  1372. {
  1373. if (taskP.taskStatus(task))
  1374. return;
  1375. else
  1376. {
  1377. taskP.taskStep(task) = 0;
  1378. (taskP.taskFrFunc(task))[0] = 0;
  1379. }
  1380. }
  1381. step = taskP.taskStep(task);
  1382. switch(step)
  1383. {
  1384. case 0:
  1385. //check if parameters valid or not
  1386. if (((CoordAddrMode != defFrmCtrl_AddrMode16)&&(CoordAddrMode != defFrmCtrl_AddrMode64))
  1387.  || (CoordPANId == 0xffff))
  1388. {
  1389. if (!autoRequest)
  1390. sscs->MLME_POLL_confirm(m_INVALID_PARAMETER);
  1391. return;
  1392. }
  1393. taskP.taskStatus(task) = true;
  1394. taskP.taskStep(task)++;
  1395. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  1396. taskP.mlme_poll_request_CoordAddrMode = CoordAddrMode;
  1397. taskP.mlme_poll_request_CoordPANId = CoordPANId;
  1398. taskP.mlme_poll_request_CoordAddress = CoordAddress;
  1399. taskP.mlme_poll_request_SecurityEnable = SecurityEnable;
  1400. taskP.mlme_poll_request_autoRequest = autoRequest;
  1401. //-- send a data request command ---
  1402. #ifdef DEBUG802_15_4
  1403. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  1404. #endif
  1405. assert(!txBcnCmd2);
  1406. txBcnCmd2 = Packet::alloc();
  1407. assert(txBcnCmd2);
  1408. wph = HDR_LRWPAN(txBcnCmd2);
  1409. if ((mpib.macShortAddress == 0xfffe)||(mpib.macShortAddress == 0xffff))
  1410. {
  1411. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode64);
  1412. wph->MHR_SrcAddrInfo.addr_64 = aExtendedAddress;
  1413. }
  1414. else
  1415. {
  1416. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode16);
  1417. wph->MHR_SrcAddrInfo.addr_16 = mpib.macShortAddress;
  1418. }
  1419. if (sfSpec2.PANCoor)
  1420. frmCtrl.setDstAddrMode(defFrmCtrl_AddrModeNone);
  1421. else
  1422. frmCtrl.setDstAddrMode(CoordAddrMode);
  1423. constructCommandHeader(txBcnCmd2,&frmCtrl,0x04,frmCtrl.dstAddrMode,CoordPANId,CoordAddress,frmCtrl.srcAddrMode,mpib.macPANId,wph->MHR_SrcAddrInfo.addr_64,SecurityEnable,false,true);
  1424. constructMPDU(1,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x04,0);
  1425. csmacaBegin('C');
  1426. //------------------------------------
  1427. break;
  1428. case 1:
  1429. if (status == p_IDLE)
  1430. {
  1431. taskP.taskStep(task)++;
  1432. strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
  1433. plme_set_trx_state_request(p_TX_ON);
  1434. break;
  1435. }
  1436. else
  1437. {
  1438. taskP.taskStatus(task) = false;
  1439. if (!autoRequest)
  1440. sscs->MLME_POLL_confirm(m_CHANNEL_ACCESS_FAILURE);
  1441. resetTRX();
  1442. taskFailed('C',m_CHANNEL_ACCESS_FAILURE);
  1443. return;
  1444. }
  1445. break;
  1446. case 2:
  1447. taskP.taskStep(task)++;
  1448. strcpy(taskP.taskFrFunc(task),"recvAck");
  1449. //enable the receiver
  1450. plme_set_trx_state_request(p_RX_ON);
  1451. txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
  1452. waitBcnCmdAck2 = true;
  1453. break;
  1454. case 3:
  1455. if (status == p_SUCCESS) //ack. received
  1456. {
  1457. if (!taskP.mlme_poll_request_pending)
  1458. {
  1459. taskP.taskStatus(task) = false;
  1460. if (!autoRequest)
  1461. sscs->MLME_POLL_confirm(m_NO_DATA);
  1462. resetTRX();
  1463. taskSuccess('C');
  1464. return;
  1465. }
  1466. else
  1467. {
  1468. taskP.taskStep(task)++;
  1469. strcpy(taskP.taskFrFunc(task),"IFSHandler");
  1470. plme_set_trx_state_request(p_RX_ON); //wait for data
  1471. taskSuccess('C',false);
  1472. extractT->start(aMaxFrameResponseTime/phy->getRate('s'),true); //wait for <aMaxFrameResponseTime> symbols (or CAP symbols if beacon enabled) (see page 156, line 1-3)
  1473. }
  1474. }
  1475. else //time out when waiting for ack.
  1476. {
  1477. numBcnCmdRetry2++;
  1478. if (numBcnCmdRetry2 <= aMaxFrameRetries)
  1479. {
  1480. taskP.taskStep(task) = 1; //important
  1481. strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
  1482. waitBcnCmdAck2 = false;
  1483. csmacaResume();
  1484. }
  1485. else
  1486. {
  1487. taskP.taskStatus(task) = false;
  1488. if (!autoRequest)
  1489. sscs->MLME_POLL_confirm(m_NO_ACK);
  1490. resetTRX();
  1491. taskFailed('C',m_NO_ACK);
  1492. return;
  1493. }
  1494. }
  1495. break;
  1496. case 4:
  1497. taskP.taskStatus(task) = false;
  1498. if (status == p_SUCCESS) //data received
  1499. {
  1500. //stop the timer
  1501. extractT->stop();
  1502. if (!autoRequest)
  1503. sscs->MLME_POLL_confirm(m_SUCCESS);
  1504. //another step is to issue DATA.indication() which has been done in IFSHandler()
  1505. //poll again to see if there are more packets pending -- note that, for each poll request, more than one confirm could be passed to upper layer
  1506. mlme_poll_request(CoordAddrMode,CoordPANId,CoordAddress,SecurityEnable,autoRequest,true);
  1507. }
  1508. else //time out when waiting for response
  1509. {
  1510. if (!autoRequest)
  1511. sscs->MLME_POLL_confirm(m_NO_DATA);
  1512. resetTRX();
  1513. csmacaResume();
  1514. }
  1515. break;
  1516. default:
  1517. break;
  1518. }
  1519. }
  1520. //-------------------------------------------------------------------------------------
  1521. void Mac802_15_4::csmacaBegin(char pktType)
  1522. {
  1523. if (pktType == 'c') //txBcnCmd
  1524. {
  1525. waitBcnCmdAck = false; //beacon packet not yet transmitted
  1526. numBcnCmdRetry = 0;
  1527. if (backoffStatus == 99) //backoffing for data packet
  1528. {
  1529. backoffStatus = 0;
  1530. csmaca->cancel();
  1531. }
  1532. csmacaResume();
  1533. }
  1534. else if (pktType == 'C') //txBcnCmd2
  1535. {
  1536. waitBcnCmdAck2 = false; //command packet not yet transmitted
  1537. numBcnCmdRetry2 = 0;
  1538. if ((backoffStatus == 99)&&(txCsmaca != txBcnCmd)) //backoffing for data packet
  1539. {
  1540. backoffStatus = 0;
  1541. csmaca->cancel();
  1542. }
  1543. csmacaResume();
  1544. }
  1545. else //if (pktType == 'd') //txData
  1546. {
  1547. waitDataAck = false; //data packet not yet transmitted
  1548. numDataRetry = 0;
  1549. csmacaResume();
  1550. }
  1551. }
  1552. void Mac802_15_4::csmacaResume(void)
  1553. {
  1554. FrameCtrl frmCtrl;
  1555. if ((backoffStatus != 99) //not during backoff
  1556. &&  (!inTransmission)) //not during transmission
  1557. if ((txBcnCmd)&&(!waitBcnCmdAck))
  1558. {
  1559. backoffStatus = 99;
  1560. frmCtrl.FrmCtrl = HDR_LRWPAN(txBcnCmd)->MHR_FrmCtrl;
  1561. frmCtrl.parse();
  1562. txCsmaca = txBcnCmd;
  1563. csmaca->start(true,txBcnCmd,frmCtrl.ackReq);
  1564. }
  1565. else if ((txBcnCmd2)&&(!waitBcnCmdAck2))
  1566. {
  1567. backoffStatus = 99;
  1568. frmCtrl.FrmCtrl = HDR_LRWPAN(txBcnCmd2)->MHR_FrmCtrl;
  1569. frmCtrl.parse();
  1570. txCsmaca = txBcnCmd2;
  1571. csmaca->start(true,txBcnCmd2,frmCtrl.ackReq);
  1572. }
  1573. else if ((txData)&&(!waitDataAck))
  1574. {
  1575. strcpy(taskP.taskFrFunc(TP_mcps_data_request),"csmacaCallBack"); //the transmission may be interrupted and need to backoff again
  1576. taskP.taskStep(TP_mcps_data_request) = 1; //also set the step
  1577. backoffStatus = 99;
  1578. frmCtrl.FrmCtrl = HDR_LRWPAN(txData)->MHR_FrmCtrl;
  1579. frmCtrl.parse();
  1580. txCsmaca = txData;
  1581. csmaca->start(true,txData,frmCtrl.ackReq);
  1582. }
  1583. }
  1584. void Mac802_15_4::csmacaCallBack(PHYenum status)
  1585. {
  1586. if (((!txBcnCmd)||(waitBcnCmdAck))
  1587.   &&((!txBcnCmd2)||(waitBcnCmdAck2))
  1588.   &&((!txData)||(waitDataAck)))
  1589. return;
  1590. backoffStatus = (status == p_IDLE)?1:2;
  1591. #ifdef DEBUG802_15_4
  1592. hdr_cmn *ch = HDR_CMN(txCsmaca);
  1593. if (status != p_IDLE)
  1594. fprintf(stdout,"[%s::%s][%f](node %d) backoff failed: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txCsmaca),p802_15_4macSA(txCsmaca),p802_15_4macDA(txCsmaca),ch->uid(),HDR_LRWPAN(txCsmaca)->uid,ch->size());
  1595. #endif
  1596. dispatch(status,__FUNCTION__);
  1597. }
  1598. int Mac802_15_4::getBattLifeExtSlotNum(void)
  1599. {
  1600. phy->PLME_GET_request(phyCurrentChannel);
  1601. return (tmp_ppib.phyCurrentChannel<=10)?8:6;
  1602. }
  1603. double Mac802_15_4::getCAP(bool small)
  1604. {
  1605. double bcnTxTime,bcnRxTime,bcnOtherRxTime,bPeriod;
  1606. double sSlotDuration,sSlotDuration2,sSlotDuration3,BI2,BI3,t_CAP,t_CAP2,t_CAP3;
  1607. double now,oneDay,tmpf;
  1608. now = CURRENT_TIME;
  1609. oneDay = now + 24.0*3600;
  1610. if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15) //non-beacon enabled
  1611. &&(macBeaconOrder3 == 15)) //no beacons from outside PAN
  1612. return oneDay; //transmission can always go ahead
  1613. bcnTxTime = macBcnTxTime / phy->getRate('s');
  1614. bcnRxTime = macBcnRxTime / phy->getRate('s');
  1615. bcnOtherRxTime = macBcnOtherRxTime / phy->getRate('s');
  1616. bPeriod = aUnitBackoffPeriod / phy->getRate('s');
  1617. sSlotDuration = sfSpec.sd / phy->getRate('s');
  1618. sSlotDuration2 = sfSpec2.sd / phy->getRate('s');
  1619. sSlotDuration3 = sfSpec3.sd / phy->getRate('s');
  1620. BI2 = (sfSpec2.BI / phy->getRate('s'));
  1621. BI3 = (sfSpec3.BI / phy->getRate('s'));
  1622. if (mpib.macBeaconOrder != 15)
  1623. {
  1624. if (sfSpec.BLE)
  1625. {
  1626. /* Linux floating number compatibility
  1627. t_CAP = (bcnTxTime + (beaconPeriods + getBattLifeExtSlotNum()) * aUnitBackoffPeriod);
  1628. */
  1629. {
  1630. tmpf = (beaconPeriods + getBattLifeExtSlotNum()) * aUnitBackoffPeriod;
  1631. t_CAP = bcnTxTime + tmpf;
  1632. }
  1633. }
  1634. else
  1635. {
  1636. /* Linux floating number compatibility
  1637. t_CAP = (bcnTxTime + (sfSpec.FinCAP + 1) * sSlotDuration);
  1638. */
  1639. {
  1640. tmpf = (sfSpec.FinCAP + 1) * sSlotDuration;
  1641. t_CAP = bcnTxTime + tmpf;
  1642. }
  1643. }
  1644. }
  1645. if (macBeaconOrder2 != 15)
  1646. {
  1647. if (sfSpec2.BLE)
  1648. {
  1649. /* Linux floating number compatibility
  1650. t_CAP2 = (bcnRxTime + (beaconPeriods2 + getBattLifeExtSlotNum()) * aUnitBackoffPeriod);
  1651. */
  1652. {
  1653. tmpf = (beaconPeriods2 + getBattLifeExtSlotNum()) * aUnitBackoffPeriod;
  1654. t_CAP2 = bcnRxTime + tmpf;
  1655. }
  1656. }
  1657. else
  1658. {
  1659. /* Linux floating number compatibility
  1660. t_CAP2 = (bcnRxTime + (sfSpec2.FinCAP + 1) * sSlotDuration2);
  1661. */
  1662. {
  1663. tmpf = (sfSpec2.FinCAP + 1) * sSlotDuration2;
  1664. t_CAP2 = bcnRxTime + tmpf;
  1665. }
  1666. }
  1667. /* Linux floating number compatibility
  1668. if ((t_CAP2 < now)&&(t_CAP2 + aMaxLostBeacons * BI2 >= now))
  1669. */
  1670. tmpf = aMaxLostBeacons * BI2;
  1671. if ((t_CAP2 < now)&&(t_CAP2 + tmpf >= now)) //no more than <aMaxLostBeacons> beacons missed
  1672. while (t_CAP2 < now)
  1673. t_CAP2 += BI2;
  1674. }
  1675. if (macBeaconOrder3 != 15)
  1676. {
  1677. //no need to handle option <macBattLifeExt> here
  1678. /* Linux floating number compatibility
  1679. t_CAP3 = (bcnOtherRxTime + (sfSpec3.FinCAP + 1) * sSlotDuration3);
  1680. */
  1681. {
  1682. tmpf = (sfSpec3.FinCAP + 1) * sSlotDuration3;
  1683. t_CAP3 = bcnOtherRxTime + tmpf;
  1684. }
  1685. /* Linux floating number compatibility
  1686. if ((t_CAP3 < now)&&(t_CAP3 + aMaxLostBeacons * BI3 >= now))
  1687. */
  1688. tmpf = aMaxLostBeacons * BI3;
  1689. if ((t_CAP3 < now)&&(t_CAP3 + tmpf >= now)) //no more than <aMaxLostBeacons> beacons missed
  1690. while (t_CAP3 < now)
  1691. t_CAP3 += BI3;
  1692. }
  1693. if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15))
  1694. {
  1695. if (t_CAP3 >= now)
  1696. return t_CAP3;
  1697. else
  1698. return oneDay;
  1699. }
  1700. else if (mpib.macBeaconOrder == 15)
  1701. {
  1702. if (t_CAP2 >= now)
  1703. return t_CAP2;
  1704. else
  1705. return oneDay;
  1706. }
  1707. else if (macBeaconOrder2 == 15)
  1708. {
  1709. if (t_CAP >= now)
  1710. return t_CAP;
  1711. else
  1712. return oneDay;
  1713. }
  1714. else
  1715. {
  1716. if (t_CAP2 < now)
  1717. return t_CAP;
  1718. if ((small)
  1719. &&  (t_CAP > t_CAP2))
  1720. t_CAP = t_CAP2;
  1721. if ((!small)
  1722. &&  (t_CAP < t_CAP2))
  1723. t_CAP = t_CAP2;
  1724. return t_CAP;
  1725. }
  1726. }
  1727. double Mac802_15_4::getCAPbyType(int type)
  1728. {
  1729. double bcnTxTime,bcnRxTime,bcnOtherRxTime,bPeriod;
  1730. double sSlotDuration,sSlotDuration2,sSlotDuration3,BI2,BI3,t_CAP,t_CAP2,t_CAP3;
  1731. double now,oneDay,tmpf;
  1732. now = CURRENT_TIME;
  1733. oneDay = now + 24.0*3600;
  1734. if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15) //non-beacon enabled
  1735. &&(macBeaconOrder3 == 15)) //no beacons from outside PAN
  1736. return oneDay; //transmission can always go ahead
  1737. bcnTxTime = macBcnTxTime / phy->getRate('s');
  1738. bcnRxTime = macBcnRxTime / phy->getRate('s');
  1739. bcnOtherRxTime = macBcnOtherRxTime / phy->getRate('s');
  1740. bPeriod = aUnitBackoffPeriod / phy->getRate('s');
  1741. sSlotDuration = sfSpec.sd / phy->getRate('s');
  1742. sSlotDuration2 = sfSpec2.sd / phy->getRate('s');
  1743. sSlotDuration3 = sfSpec3.sd / phy->getRate('s');
  1744. BI2 = (sfSpec2.BI / phy->getRate('s'));
  1745. BI3 = (sfSpec3.BI / phy->getRate('s'));
  1746. if (type == 1)
  1747. if (mpib.macBeaconOrder != 15)
  1748. {
  1749. if (sfSpec.BLE)
  1750. {
  1751. /* Linux floating number compatibility
  1752. t_CAP = (bcnTxTime + (beaconPeriods + getBattLifeExtSlotNum()) * aUnitBackoffPeriod);
  1753. */
  1754. {
  1755. tmpf = (beaconPeriods + getBattLifeExtSlotNum()) * aUnitBackoffPeriod;
  1756. t_CAP = bcnTxTime + tmpf;
  1757. }
  1758. }
  1759. else
  1760. {
  1761. /* Linux floating number compatibility
  1762. t_CAP = (bcnTxTime + (sfSpec.FinCAP + 1) * sSlotDuration);
  1763. */
  1764. {
  1765. tmpf = (sfSpec.FinCAP + 1) * sSlotDuration;
  1766. t_CAP = bcnTxTime + tmpf;
  1767. }
  1768. }
  1769. return (t_CAP>=now)?t_CAP:oneDay;
  1770. }
  1771. else
  1772. return oneDay;
  1773. if (type == 2)
  1774. if (macBeaconOrder2 != 15)
  1775. {
  1776. if (sfSpec2.BLE)
  1777. {
  1778. /* Linux floating number compatibility
  1779. t_CAP2 = (bcnRxTime + (beaconPeriods2 + getBattLifeExtSlotNum()) * aUnitBackoffPeriod);
  1780. */
  1781. {
  1782. tmpf = (beaconPeriods2 + getBattLifeExtSlotNum()) * aUnitBackoffPeriod;
  1783. t_CAP2 = bcnRxTime + tmpf;
  1784. }
  1785. }
  1786. else
  1787. {
  1788. /* Linux floating number compatibility
  1789. t_CAP2 = (bcnRxTime + (sfSpec2.FinCAP + 1) * sSlotDuration2);
  1790. */
  1791. {
  1792. tmpf = (sfSpec2.FinCAP + 1) * sSlotDuration2;
  1793. t_CAP2 = bcnRxTime + tmpf;
  1794. }
  1795. }
  1796. /* Linux floating number compatibility
  1797. if ((t_CAP2 < now)&&(t_CAP2 + aMaxLostBeacons * BI2 >= now))
  1798. */
  1799. tmpf = aMaxLostBeacons * BI2;
  1800. if ((t_CAP2 < now)&&(t_CAP2 + tmpf >= now)) //no more than <aMaxLostBeacons> beacons missed
  1801. while (t_CAP2 < now)
  1802. t_CAP2 += BI2;
  1803. return (t_CAP2>=now)?t_CAP2:oneDay;
  1804. }
  1805. else
  1806. return oneDay;
  1807. if (type == 3)
  1808. if (macBeaconOrder3 != 15)
  1809. {
  1810. //no need to handle option <macBattLifeExt> here
  1811. /* Linux floating number compatibility
  1812. t_CAP3 = (bcnOtherRxTime + (sfSpec3.FinCAP + 1) * sSlotDuration3);
  1813. */
  1814. {
  1815. tmpf = (sfSpec3.FinCAP + 1) * sSlotDuration3;
  1816. t_CAP3 = bcnOtherRxTime + tmpf;
  1817. }
  1818. /* Linux floating number compatibility
  1819. if ((t_CAP3 < now)&&(t_CAP3 + aMaxLostBeacons * BI3 >= now))
  1820. */
  1821. tmpf = aMaxLostBeacons * BI3;
  1822. if ((t_CAP3 < now)&&(t_CAP3 + tmpf >= now)) //no more than <aMaxLostBeacons> beacons missed
  1823. while (t_CAP3 < now)
  1824. t_CAP3 += BI3;
  1825. return (t_CAP3>=now)?t_CAP3:oneDay;
  1826. }
  1827. else
  1828. return oneDay;
  1829. return oneDay;
  1830. }
  1831. bool Mac802_15_4::canProceedWOcsmaca(Packet *p)
  1832. {
  1833. //this function checks whether there is enough time in the CAP of current superframe to finish a transaction (transmit a pending packet to a device)
  1834. //(in the case the node acts as both a coordinator and a device, both the superframes from and to this node should be taken into account)
  1835. double wtime,t_IFS,t_transacTime,t_CAP,tmpf;
  1836. FrameCtrl frmCtrl;
  1837. //int type;
  1838. if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15)
  1839. &&(macBeaconOrder3 == 15))
  1840. return true;
  1841. else
  1842. {
  1843. frmCtrl.FrmCtrl = HDR_LRWPAN(p)->MHR_FrmCtrl;
  1844. frmCtrl.parse();
  1845. wtime = 0.0;
  1846. //there is no need to consider <macBattLifeExt>, since the device polling the data 
  1847. //should be waiting rather than go to sleep after the first 6 CAP backoff perios.
  1848. if (HDR_CMN(p)->size() <= aMaxSIFSFrameSize)
  1849. t_IFS = aMinSIFSPeriod;
  1850. else
  1851. t_IFS = aMinLIFSPeriod;
  1852. t_IFS /= phy->getRate('s');
  1853. t_transacTime  = locateBoundary(toParent(p),wtime) - wtime; //boundary location time
  1854. t_transacTime += phy->trxTime(p); //packet transmission time
  1855. if (frmCtrl.ackReq)
  1856. {
  1857. t_transacTime += mpib.macAckWaitDuration/phy->getRate('s'); //ack. waiting time
  1858. t_transacTime += 2*max_pDelay; //round trip propagation delay (802.15.4 ignores this, but it should be there even though it is very small)
  1859. t_transacTime += t_IFS; //IFS time -- not only ensure that the sender can finish the transaction, but also the receiver
  1860. t_CAP = getCAP(true);
  1861. /* Linux floating number compatibility
  1862. if (CURRENT_TIME + wtime + t_transacTime > t_CAP)
  1863. */
  1864. tmpf = CURRENT_TIME + wtime;
  1865. tmpf += t_transacTime;
  1866. if (tmpf > t_CAP)
  1867. return false;
  1868. else
  1869. return true;
  1870. }
  1871. else
  1872. {
  1873. //in this case, we need to handle individual CAP 
  1874. t_CAP = getCAPbyType(1);
  1875. /* Linux floating number compatibility
  1876. if (CURRENT_TIME + wtime + t_transacTime > t_CAP)
  1877. */
  1878. tmpf = CURRENT_TIME + wtime;
  1879. tmpf += t_transacTime;
  1880. if (tmpf > t_CAP)
  1881. return false;
  1882. t_CAP = getCAPbyType(2);
  1883. t_transacTime += max_pDelay; //one-way trip propagation delay (802.15.4 ignores this, but it should be there even though it is very small)
  1884. t_transacTime += 12/phy->getRate('s'); //transceiver turn-around time (receiver may need to do this to transmit next beacon)
  1885. t_transacTime += t_IFS; //IFS time -- not only ensure that the sender can finish the transaction, but also the receiver
  1886. /* Linux floating number compatibility
  1887. if (CURRENT_TIME + wtime + t_transacTime > t_CAP)
  1888. */
  1889. tmpf = CURRENT_TIME + wtime;
  1890. tmpf += t_transacTime;
  1891. if (tmpf > t_CAP)
  1892. return false;
  1893. t_CAP = getCAPbyType(3);
  1894. t_transacTime -= t_IFS; //the third node does not need to handle the transaction
  1895. /* Linux floating number compatibility
  1896. if (CURRENT_TIME + wtime + t_transacTime > t_CAP)
  1897. */
  1898. tmpf = CURRENT_TIME + wtime;
  1899. tmpf += t_transacTime;
  1900. if (tmpf > t_CAP)
  1901. return false;
  1902. return true;
  1903. }
  1904. }
  1905. }
  1906. void Mac802_15_4::transmitCmdData(void)
  1907. {
  1908. double delay;
  1909. if ((mpib.macBeaconOrder != 15)||(macBeaconOrder2 != 15)) //beacon enabled -- slotted
  1910. {
  1911. delay =locateBoundary(toParent(txCsmaca),0.0);
  1912. if(delay > 0.0)
  1913. {
  1914. Scheduler::instance().schedule(&txCmdDataH, &(txCmdDataH.nullEvent), delay);
  1915. return;
  1916. }
  1917. }
  1918. //transmit immediately
  1919. txBcnCmdDataHandler();
  1920. }
  1921. void Mac802_15_4::reset_TRX(const char *frFile,const char *frFunc,int line)
  1922. {
  1923. double t_CAP;
  1924. PHYenum t_state;
  1925. if ((mpib.macBeaconOrder != 15)||(macBeaconOrder2 != 15)) //beacon enabled
  1926. {
  1927. //according to the draft, <macRxOnWhenIdle> only considered during idle periods of the CAP if beacon enabled
  1928. t_CAP = getCAP(false);
  1929. if (CURRENT_TIME < t_CAP)
  1930. t_state = mpib.macRxOnWhenIdle?p_RX_ON:p_TRX_OFF;
  1931. else
  1932. t_state = p_RX_ON; //(not considered ==> RX_ON)?
  1933. }
  1934. else
  1935. t_state = mpib.macRxOnWhenIdle?p_RX_ON:p_TRX_OFF;
  1936. set_trx_state_request(t_state,frFile,frFunc,line);
  1937. }
  1938. void Mac802_15_4::taskSuccess(char task,bool csmacaRes)
  1939. {
  1940. hdr_cmn* ch;
  1941. hdr_lrwpan* wph;
  1942. UINT_16 t_CAP;
  1943. UINT_8 ifs;
  1944. double tmpf;
  1945. #ifdef DEBUG802_15_4
  1946. fprintf(stdout,"[%s::%s][%f](node %d) task '%c' successful:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,task,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  1947. #endif
  1948. if (task == 'b') //beacon
  1949. {
  1950. if (!txBeacon)
  1951. {
  1952. assert(txBcnCmd2);
  1953. txBeacon = txBcnCmd2;
  1954. txBcnCmd2 = 0;
  1955. }
  1956. //--- calculate CAP ---
  1957. sfSpec.parse();
  1958. if (HDR_CMN(txBeacon)->size() <= aMaxSIFSFrameSize)
  1959. ifs = aMinSIFSPeriod;
  1960. else
  1961. ifs = aMinLIFSPeriod;
  1962. /* Linux floating number compatibility
  1963. beaconPeriods = (UINT_8)((phy->trxTime(txBeacon) * phy->getRate('s') + ifs) / aUnitBackoffPeriod);
  1964. */
  1965. {
  1966. tmpf = phy->trxTime(txBeacon) * phy->getRate('s');
  1967. tmpf += ifs;
  1968. beaconPeriods = (UINT_8)(tmpf / aUnitBackoffPeriod);
  1969. }
  1970. /* Linux floating number compatibility
  1971. if (fmod((phy->trxTime(txBeacon) * phy->getRate('s')+ ifs) ,aUnitBackoffPeriod) > 0.0)
  1972. */
  1973. tmpf = phy->trxTime(txBeacon) * phy->getRate('s');
  1974. tmpf += ifs;
  1975. if (fmod(tmpf,aUnitBackoffPeriod) > 0.0)
  1976. beaconPeriods++;
  1977. t_CAP = (sfSpec.FinCAP + 1) * (sfSpec.sd / aUnitBackoffPeriod) - beaconPeriods;
  1978. if (t_CAP == 0)
  1979. {
  1980. csmacaRes = false;
  1981. plme_set_trx_state_request(p_TRX_OFF);
  1982. }
  1983. else
  1984. plme_set_trx_state_request(p_RX_ON);
  1985. //CSMA-CA may be waiting for the new beacon
  1986. if (backoffStatus == 99)
  1987. csmaca->newBeacon('t');
  1988. //----------------------
  1989. beaconWaiting = false;
  1990. Packet::free(txBeacon);
  1991. txBeacon = 0;
  1992. /*
  1993. //send out delayed ack.
  1994. if (txAck)
  1995. {
  1996. csmacaRes = false;
  1997. plme_set_trx_state_request(p_TX_ON);
  1998. }
  1999. */
  2000. }
  2001. else if (task == 'a') //ack.
  2002. {
  2003. assert(txAck);
  2004. Packet::free(txAck);
  2005. txAck = 0;
  2006. }
  2007. else if (task == 'c') //command
  2008. {
  2009. assert(txBcnCmd);
  2010. //if it is a pending packet, delete it from the pending list
  2011. updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,txBcnCmd);
  2012. freePkt(txBcnCmd);
  2013. txBcnCmd = 0;
  2014. }
  2015. else if (task == 'C') //command
  2016. {
  2017. assert(txBcnCmd2);
  2018. freePkt(txBcnCmd2);
  2019. txBcnCmd2 = 0;
  2020. }
  2021. else if (task == 'd') //data
  2022. {
  2023. assert(txData);
  2024. ch = HDR_CMN(txData);
  2025. wph = HDR_LRWPAN(txData);
  2026. Packet *p = txData;
  2027. txData = 0;
  2028. if (ch->ptype() == PT_MAC)
  2029. {
  2030. assert(wph->msduHandle);
  2031. sscs->MCPS_DATA_confirm(wph->msduHandle,m_SUCCESS);
  2032. }
  2033. else
  2034. {
  2035. if (Mac802_15_4::callBack == 2)
  2036. if (ch->xmit_failure_)
  2037. if (p802_15_4macDA(p) != (nsaddr_t)MAC_BROADCAST)
  2038. {
  2039. ch->size() -= macHeaderLen(wph->MHR_FrmCtrl);
  2040. ch->xmit_reason_ = 1;
  2041. ch->xmit_failure_(p->refcopy(),ch->xmit_failure_data_);
  2042. }
  2043. if (callback_)
  2044. {
  2045. Handler *h = callback_;
  2046. callback_ = 0;
  2047. h->handle((Event*) 0);
  2048. }
  2049. }
  2050. //if it is a pending packet, delete it from the pending list
  2051. updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,p);
  2052. freePkt(p);
  2053. }
  2054. else
  2055. assert(0);
  2056. if (csmacaRes)
  2057. csmacaResume();
  2058. }
  2059. void Mac802_15_4::taskFailed(char task,MACenum status,bool csmacaRes)
  2060. {
  2061. hdr_cmn* ch;
  2062. hdr_lrwpan* wph;
  2063. #ifdef DEBUG802_15_4
  2064. fprintf(stdout,"[D][FAIL][%s::%s][%f](node %d) task '%c' failed:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,task,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  2065. #endif
  2066. if ((task == 'b') //beacon
  2067. || (task == 'a') //ack.
  2068. || (task == 'c')) //command
  2069. {
  2070. assert(0); //we don't handle the above failures here
  2071. }
  2072. else if (task == 'C') //command
  2073. {
  2074. freePkt(txBcnCmd2);
  2075. txBcnCmd2 = 0;
  2076. }
  2077. else if (task == 'd') //data
  2078. {
  2079. wph = HDR_LRWPAN(txData);
  2080. ch = HDR_CMN(txData);
  2081. #ifdef DEBUG802_15_4
  2082. fprintf(stdout,"[D][FAIL][%s::%s::%d][%f](node %d) failure: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %dn",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(txData),p802_15_4macSA(txData),p802_15_4macDA(txData),ch->uid(),wph->uid,ch->size());
  2083. #endif
  2084. Packet *p = txData;
  2085. txData = 0;
  2086. if (wph->msduHandle) //from SSCS
  2087. sscs->MCPS_DATA_confirm(wph->msduHandle,status);
  2088. else
  2089. {
  2090. if (Mac802_15_4::callBack)
  2091. if (ch->xmit_failure_)
  2092. {
  2093. wph->setSN = true;
  2094. ch->size() -= macHeaderLen(wph->MHR_FrmCtrl);
  2095. ch->xmit_reason_ = 0;
  2096. ch->xmit_failure_(p->refcopy(),ch->xmit_failure_data_);
  2097. }
  2098. if (callback_
  2099. && (!dataWaitT->busy()))
  2100. {
  2101. Handler *h = callback_;
  2102. callback_ = 0;
  2103. h->handle((Event*) 0);
  2104. }
  2105. }
  2106. freePkt(p);
  2107. }
  2108. else
  2109. assert(0);
  2110. if (csmacaRes)
  2111. csmacaResume();
  2112. }
  2113. void Mac802_15_4::freePkt(Packet *pkt)
  2114. {
  2115. /*
  2116. if (HDR_LRWPAN(pkt)->indirect)
  2117. return; //the packet will be automatically deleted when expired
  2118. else
  2119. Packet::free(pkt);
  2120. */
  2121. Packet::free(pkt); //now same operation for directly transmitted and indirectly transmitted packets
  2122. }
  2123. UINT_8 Mac802_15_4::macHeaderLen(UINT_16 FrmCtrl)
  2124. {
  2125. //calculate the MAC sublayer header (also including footer) length
  2126. UINT_8 macHLen;
  2127. FrameCtrl frmCtrl;
  2128. frmCtrl.FrmCtrl = FrmCtrl;
  2129. frmCtrl.parse();
  2130. macHLen = 0;
  2131. macHLen += 2 //FrmCtrl
  2132.   +1 //BSN/DSN
  2133.   +2; //FCS
  2134. if (frmCtrl.frmType == defFrmCtrl_Type_Beacon) //Beacon
  2135. {
  2136. if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode16)
  2137. macHLen += 2;
  2138. else if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode64)
  2139. macHLen += 8;
  2140. }
  2141. else if ((frmCtrl.frmType == defFrmCtrl_Type_Data) //Data
  2142. ||(frmCtrl.frmType == defFrmCtrl_Type_MacCmd)) //Mac Command
  2143. {
  2144. if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode16)
  2145. macHLen += 2;
  2146. else if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64)
  2147. macHLen += 8;
  2148. if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode16)
  2149. macHLen += 2;
  2150. else if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode64)
  2151. macHLen += 8;
  2152. }
  2153. else if (frmCtrl.frmType == defFrmCtrl_Type_Ack) //Ack.
  2154. {
  2155. ;//nothing to do
  2156. }
  2157. else
  2158. fprintf(stdout,"[%s][%f](node %d) Invalid frame type!n",__FUNCTION__,CURRENT_TIME,index_);
  2159. return macHLen;
  2160. }
  2161. void Mac802_15_4::constructACK(Packet *p)
  2162. {
  2163. bool intraPan;
  2164. UINT_8 origFrmType;
  2165. FrameCtrl frmCtrl;
  2166. Packet *ack = Packet::alloc();
  2167. hdr_lrwpan* wph1 = HDR_LRWPAN(p);
  2168. hdr_lrwpan* wph2 = HDR_LRWPAN(ack);
  2169. hdr_cmn* ch1 = HDR_CMN(p);
  2170. hdr_cmn* ch2 = HDR_CMN(ack);
  2171. int i;
  2172. hdr_dst((char *)HDR_MAC(ack),p802_15_4macSA(p));
  2173. hdr_src((char *)HDR_MAC(ack),index_);
  2174. frmCtrl.FrmCtrl = wph1->MHR_FrmCtrl;
  2175. frmCtrl.parse();
  2176. intraPan = frmCtrl.intraPan;
  2177. origFrmType = frmCtrl.frmType;
  2178. frmCtrl.FrmCtrl = 0;
  2179. frmCtrl.setFrmType(defFrmCtrl_Type_Ack);
  2180. frmCtrl.setSecu(false);
  2181. //if it is a data request command, then need to check if there is any packet pending.
  2182. //In implementation, we may not have enough time to check if packets pending. If this is the case,
  2183. //then the pending flag in the ack. should be set to 1, and then send a zero-length data packet
  2184. //if later it turns out there is no packet actually pending.
  2185. //In simulation, we assume having enough time to determine the pending status -- so zero-length packet will never be sent.
  2186. //(refer to page 155, line 46-50)
  2187. if ((origFrmType == defFrmCtrl_Type_MacCmd) //command packet
  2188. && (wph1->MSDU_CmdType == 0x04)) //data request command
  2189. {
  2190. i = updateTransacLink(tr_oper_est,&transacLink1,&transacLink2,frmCtrl.srcAddrMode,wph1->MHR_SrcAddrInfo.addr_64);
  2191. frmCtrl.setFrmPending(i==0);
  2192. }
  2193. else
  2194. frmCtrl.setFrmPending(false);
  2195. frmCtrl.setAckReq(false);
  2196. frmCtrl.setIntraPan(intraPan);
  2197. frmCtrl.setDstAddrMode(defFrmCtrl_AddrModeNone);
  2198. frmCtrl.setSrcAddrMode(defFrmCtrl_AddrModeNone);
  2199. wph2->MHR_FrmCtrl = frmCtrl.FrmCtrl;
  2200. wph2->MHR_BDSN = wph1->MHR_BDSN; //copy the SN from Data/MacCmd packet
  2201. wph2->uid = wph1->uid; //for debug
  2202. //wph2->MFR_FCS
  2203. ch2->uid() = 0;
  2204. ch2->ptype() = PT_MAC;
  2205. ch2->iface() = -2;
  2206. ch2->error() = 0;
  2207. ch2->size() = 5;
  2208. ch2->uid() = ch1->uid(); //copy the uid
  2209. ch2->next_hop_ = p802_15_4macDA(ack); //nam needs the nex_hop information
  2210. p802_15_4hdrACK(ack);
  2211. #ifdef DEBUG802_15_4
  2212. fprintf(stdout,"[%s::%s][%f](node %d) before alloc txAck:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  2213. #endif
  2214. assert(!txAck); //it's impossilbe to receive the second packet before
  2215. //the Ack has been sent out.
  2216. txAck = ack;
  2217. }
  2218. void Mac802_15_4::constructMPDU(UINT_8 msduLength,Packet *msdu, UINT_16 FrmCtrl,UINT_8 BDSN,panAddrInfo DstAddrInfo,
  2219.  panAddrInfo  SrcAddrInfo,UINT_16 SuperSpec,UINT_8 CmdType,UINT_16 FCS)
  2220. {
  2221. hdr_lrwpan* wph = HDR_LRWPAN(msdu);
  2222. hdr_cmn* ch = HDR_CMN(msdu);
  2223. //FrameCtrl frmCtrl;
  2224. //fill out fields
  2225. wph->MHR_FrmCtrl = FrmCtrl;
  2226. if (!wph->setSN)
  2227. wph->MHR_BDSN = BDSN;
  2228. else
  2229. wph->setSN = false;
  2230. if (!wph->uid)
  2231. wph->uid = Mac802_15_4::DBG_UID++;
  2232. wph->MHR_DstAddrInfo = DstAddrInfo;
  2233. wph->MHR_SrcAddrInfo = SrcAddrInfo;
  2234. wph->MSDU_SuperSpec = SuperSpec;
  2235. wph->MSDU_CmdType = CmdType;
  2236. wph->MFR_FCS = FCS;
  2237. //update packet length
  2238. ch->size() = msduLength + macHeaderLen(FrmCtrl);
  2239. }
  2240. void Mac802_15_4::constructCommandHeader(Packet *p,FrameCtrl *frmCtrl,UINT_8 CmdType,
  2241. UINT_8 dstAddrMode,UINT_16 dstPANId,IE3ADDR dstAddr,
  2242. UINT_8 srcAddrMode,UINT_16 srcPANId,IE3ADDR srcAddr,
  2243. bool secuEnable,bool pending,bool ackreq)
  2244. {
  2245. hdr_lrwpan *wph = HDR_LRWPAN(p);
  2246. frmCtrl->FrmCtrl = 0;
  2247. frmCtrl->setFrmType(defFrmCtrl_Type_MacCmd);
  2248. frmCtrl->setDstAddrMode(dstAddrMode);
  2249. wph->MHR_DstAddrInfo.panID = dstPANId;
  2250. wph->MHR_DstAddrInfo.addr_64 = dstAddr;
  2251. hdr_src((char *)HDR_MAC(p),index_);
  2252. if (dstAddr == 0xffff)
  2253. hdr_dst((char *)HDR_MAC(p),MAC_BROADCAST);
  2254. else
  2255. hdr_dst((char *)HDR_MAC(p),dstAddr);
  2256. frmCtrl->setSrcAddrMode(srcAddrMode);
  2257. wph->MHR_SrcAddrInfo.panID = srcPANId;
  2258. wph->MHR_SrcAddrInfo.addr_64 = srcAddr;
  2259. frmCtrl->setSecu(secuEnable);
  2260. frmCtrl->setFrmPending(pending);
  2261. frmCtrl->setAckReq(ackreq);
  2262. HDR_CMN(p)->ptype() = PT_MAC;
  2263. //for trace purpose
  2264. HDR_CMN(p)->next_hop_ = p802_15_4macDA(p); //nam needs the nex_hop information
  2265. p802_15_4hdrCommand(p,CmdType);
  2266. }
  2267. void Mac802_15_4::log(Packet *p)
  2268. {
  2269. logtarget_->recv(p, (Handler*) 0);
  2270. }
  2271. void Mac802_15_4::resetCounter(int dst)
  2272. {
  2273. if (txBcnCmd)
  2274. if (p802_15_4macDA(txBcnCmd) == dst)
  2275. numBcnCmdRetry = 0;
  2276. if (txBcnCmd2)
  2277. if (p802_15_4macDA(txBcnCmd2) == dst)
  2278. numBcnCmdRetry2 = 0;
  2279. if (txData)
  2280. if (p802_15_4macDA(txData) == dst)
  2281. numDataRetry = 0;
  2282. }
  2283. int Mac802_15_4::command(int argc, const char*const* argv)
  2284. {
  2285. if (argc == 3)
  2286. {
  2287. if (strcmp(argv[1], "log-target") == 0)
  2288. {
  2289. logtarget_ = (NsObject*) TclObject::lookup(argv[2]);
  2290. if(logtarget_ == 0)
  2291. return TCL_ERROR;
  2292. return TCL_OK;
  2293. }
  2294. }
  2295. if (strcmp(argv[1], "NodeClr") == 0)
  2296. {
  2297. changeNodeColor(CURRENT_TIME,argv[2]);
  2298. return (TCL_OK);
  2299. }
  2300. if (strcmp(argv[1], "NodeLabel") == 0)
  2301. {
  2302. char label[81];
  2303. int i;
  2304. strcpy(label,""");
  2305. strcat(label,argv[2]);
  2306. i = 3;
  2307. while (i < argc)
  2308. {
  2309. if (strlen(label) + strlen(argv[i]) < 78)
  2310. {
  2311. strcat(label," ");
  2312. strcat(label,argv[i]);
  2313. }
  2314. else
  2315. break;
  2316. i++;
  2317. }
  2318. strcat(label,""");
  2319. nam->changeLabel(CURRENT_TIME,label);
  2320. return (TCL_OK);
  2321. }
  2322. if (strcmp(argv[1], "node-down") == 0)
  2323. {
  2324. chkAddNFailLink(index_);
  2325. changeNodeColor(CURRENT_TIME,Nam802_15_4::def_NodeFail_clr);
  2326. if (txAck)
  2327. {
  2328. Packet::free(txAck);
  2329. txAck = 0;
  2330. }
  2331. if (txBcnCmd)
  2332. {
  2333. freePkt(txBcnCmd);
  2334. txBcnCmd = 0;
  2335. }
  2336. if (txBcnCmd2)
  2337. {
  2338. freePkt(txBcnCmd2);
  2339. txBcnCmd2 = 0;
  2340. }
  2341. if (txData)
  2342. {
  2343. freePkt(txData);
  2344. txData = 0;
  2345. }
  2346. if (phy->rxPacket())
  2347. HDR_CMN(phy->rxPacket())->error() = 1;
  2348. init(true); //reset
  2349. return (TCL_OK);
  2350. }
  2351. if (strcmp(argv[1], "node-up") == 0)
  2352. {
  2353. updateNFailLink(fl_oper_del,index_);
  2354. nam->changeBackNodeColor(CURRENT_TIME);
  2355. init(true); //reset
  2356. if (callback_)
  2357. {
  2358. Handler *h = callback_;
  2359. callback_ = 0;
  2360. h->handle((Event*) 0);
  2361. }
  2362. return (TCL_OK);
  2363. }
  2364. //check if this is actually a SSCS command
  2365. if ((argc >= 3)&&(strcmp(argv[1],"sscs") == 0))
  2366. return sscs->command(argc,argv);
  2367. int rt = Mac::command(argc, argv);
  2368. //check if Mac::command has already populated netif_
  2369. if (netif_)
  2370. if (phy == NULL) //only execute once
  2371. {
  2372. phy = (Phy802_15_4 *)netif_;
  2373. phy->macObj(this);
  2374. csmaca = new CsmaCA802_15_4(phy,this);
  2375. assert(csmaca);
  2376. }
  2377. return rt;
  2378. }
  2379. void Mac802_15_4::changeNodeColor(double atTime,const char *newColor,bool save)
  2380. {
  2381. nam->changeNodeColor(atTime,newColor,save);
  2382. nam->changeNodeColor(atTime+0.030001,newColor,false);
  2383. }
  2384. void Mac802_15_4::txBcnCmdDataHandler(void)
  2385. {
  2386. int i;
  2387. if (taskP.taskStatus(TP_mlme_scan_request))
  2388. if (txBcnCmd2 != txCsmaca)
  2389. return; //terminate all other transmissions (will resume afte channel scan)
  2390. if (HDR_LRWPAN(txCsmaca)->indirect)
  2391. {
  2392. i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,txCsmaca);
  2393. if (i != 0) //transaction expired
  2394. {
  2395. resetTRX();
  2396. if (txBcnCmd == txCsmaca)
  2397. txBcnCmd = 0;
  2398. else if (txBcnCmd2 == txCsmaca)
  2399. txBcnCmd2 = 0;
  2400. else if (txData == txCsmaca)
  2401. txData = 0;
  2402. //Packet::free(txCsmaca); //don't do this, since the packet will be automatically deleted when expired
  2403. csmacaResume();
  2404. return;
  2405. }
  2406. }
  2407. if (txBcnCmd == txCsmaca)
  2408. {
  2409. #ifdef DEBUG802_15_4
  2410. FrameCtrl frmCtrl;
  2411. frmCtrl.FrmCtrl = HDR_LRWPAN(txBcnCmd)->MHR_FrmCtrl;
  2412. frmCtrl.parse();
  2413. /*
  2414. char frm_type[21];
  2415. if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
  2416. strcpy(frm_type,"BEACON");
  2417. else
  2418. sprintf(frm_type,"COMMAND_%d",HDR_LRWPAN(txBcnCmd)->MSDU_CmdType);
  2419. */
  2420. fprintf(stdout,"[%s::%s][%f](node %d) transmit %s to %d: SN = %d, uid = %d, mac_uid = %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txBcnCmd),p802_15_4macDA(txBcnCmd),HDR_LRWPAN(txBcnCmd)->MHR_BDSN,HDR_CMN(txBcnCmd)->uid(),HDR_LRWPAN(txBcnCmd)->uid);
  2421. #endif
  2422. txPkt = txBcnCmd;
  2423. HDR_CMN(txBcnCmd)->direction() = hdr_cmn::DOWN;
  2424. sendDown(txBcnCmd->copy(), this);
  2425. }
  2426. else if (txBcnCmd2 == txCsmaca)
  2427. {
  2428. #ifdef DEBUG802_15_4
  2429. FrameCtrl frmCtrl2;
  2430. frmCtrl2.FrmCtrl = HDR_LRWPAN(txBcnCmd2)->MHR_FrmCtrl;
  2431. frmCtrl2.parse();
  2432. /*
  2433. char frm_type2[21];
  2434. if (frmCtrl2.frmType == defFrmCtrl_Type_Beacon)
  2435. strcpy(frm_type2,"BEACON");
  2436. else
  2437. sprintf(frm_type2,"COMMAND_%d",HDR_LRWPAN(txBcnCmd2)->MSDU_CmdType);
  2438. */
  2439. fprintf(stdout,"[%s::%s][%f](node %d) transmit %s to %d: SN = %d, uid = %d, mac_uid = %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txBcnCmd2),p802_15_4macDA(txBcnCmd2),HDR_LRWPAN(txBcnCmd2)->MHR_BDSN,HDR_CMN(txBcnCmd2)->uid(),HDR_LRWPAN(txBcnCmd2)->uid);
  2440. #endif
  2441. txPkt = txBcnCmd2;
  2442. HDR_CMN(txBcnCmd2)->direction() = hdr_cmn::DOWN;
  2443. sendDown(txBcnCmd2->copy(), this);
  2444. }
  2445. else if (txData == txCsmaca)
  2446. {
  2447. #ifdef DEBUG802_15_4
  2448. fprintf(stdout,"[%s::%s][%f](node %d) transmit DATA (%s) to %d: SN = %d, uid = %d, mac_uid = %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txData),p802_15_4macDA(txData),HDR_LRWPAN(txData)->MHR_BDSN,HDR_CMN(txData)->uid(),HDR_LRWPAN(txData)->uid);
  2449. #endif
  2450. txPkt = txData;
  2451. HDR_CMN(txData)->direction() = hdr_cmn::DOWN;
  2452. sendDown(txData->copy(), this);
  2453. }
  2454. }
  2455. void Mac802_15_4::IFSHandler(void)
  2456. {
  2457. hdr_lrwpan* wph;
  2458. hdr_cmn* ch;
  2459. FrameCtrl frmCtrl;
  2460. Packet *pendPkt;
  2461. MACenum status;
  2462. int i;
  2463. assert(rxData||rxCmd);
  2464. if (rxCmd)
  2465. {
  2466. wph = HDR_LRWPAN(rxCmd);
  2467. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2468. frmCtrl.parse();
  2469. if (wph->MSDU_CmdType == 0x01) //Association request
  2470. sscs->MLME_ASSOCIATE_indication(wph->MHR_SrcAddrInfo.addr_64,wph->MSDU_Payload[0],frmCtrl.secu,0); //ACL ignored in simulation
  2471. else if (wph->MSDU_CmdType == 0x02) //Association response
  2472. {
  2473. status = (*(MACenum *)(wph->MSDU_Payload + 2));
  2474. //save the short address (if association successful)
  2475. if (status == m_SUCCESS)
  2476. mpib.macShortAddress = *((UINT_16 *)wph->MSDU_Payload);
  2477. dispatch(p_SUCCESS,__FUNCTION__,p_SUCCESS,status);
  2478. }
  2479. else if (wph->MSDU_CmdType == 0x04) //Data request
  2480. {
  2481. //Continue to send pending packet (an ack. already sent).
  2482. //In implementation, we may not have enough time to check if packets pending. If this is the case,
  2483. //then the pending flag in the ack. should be set to 1, and then send a zero-length data packet
  2484. //if later it turns out there is no packet actually pending.
  2485. //In simulation, we assume having enough time to determine the pending status -- so zero-length packet will never be sent.
  2486. //(refer to page 155, line 46-50)
  2487. i = updateTransacLink(tr_oper_EST,&transacLink1,&transacLink2,frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.addr_64);
  2488. if (i != 0)
  2489. {
  2490. i = updateTransacLink(tr_oper_est,&transacLink1,&transacLink2,frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.addr_64);
  2491. i = (i == 0)?1:0;
  2492. }
  2493. else //more than one packet pending
  2494. {
  2495. i = 2;
  2496. }
  2497. if (i > 0) //packet(s) pending
  2498. {
  2499. pendPkt = getPktFrTransacLink(&transacLink1,frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.addr_64);
  2500. wph = HDR_LRWPAN(pendPkt);
  2501. wph->indirect = true;
  2502. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2503. frmCtrl.parse();
  2504. frmCtrl.setFrmPending(i>1); //more packet pending?
  2505. wph->MHR_FrmCtrl = frmCtrl.FrmCtrl;
  2506. HDR_CMN(pendPkt)->direction() = hdr_cmn::DOWN;
  2507. if (frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
  2508. {
  2509. if (txBcnCmd == pendPkt) //it's being processed
  2510. {
  2511. Packet::free(rxCmd); //we logged the command packet before, here just free it
  2512. rxCmd = 0;
  2513. return;
  2514. }
  2515. #ifdef DEBUG802_15_4
  2516. fprintf(stdout,"[%s::%s][%f](node %d) before assign txBcnCmd:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  2517. #endif
  2518. assert(!txBcnCmd); //we couldn't receive the data request command if we are processing txBcnCmd
  2519. txBcnCmd = pendPkt->refcopy();
  2520. waitBcnCmdAck = false;
  2521. numBcnCmdRetry = 0;
  2522. }
  2523. else if (frmCtrl.frmType == defFrmCtrl_Type_Data)
  2524. {
  2525. if (txData == pendPkt) //it's being processed
  2526. {
  2527. Packet::free(rxCmd); //we logged the command packet before, here just free it
  2528. rxCmd = 0;
  2529. return;
  2530. }
  2531. #ifdef DEBUG802_15_4
  2532. fprintf(stdout,"[%s::%s][%f](node %d) before assign txData:ntttxBeacont= %ldntttxAck   t= %ldntttxBcnCmdt= %ldntttxBcnCmd2t= %ldntttxData  t= %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
  2533. #endif
  2534. assert(!txData); //we couldn't receive the data request command if we are processing txData
  2535. txData = pendPkt->refcopy();
  2536. waitDataAck = false;
  2537. numDataRetry = 0;
  2538. }
  2539. //there are two ways to transmit the pending packet for the first time (refer to page 156), w/o or w/ CSMA-CA,
  2540. if (canProceedWOcsmaca(pendPkt))
  2541. {
  2542. //change task field "frFunc"
  2543. if(taskP.taskStatus(TP_mcps_data_request))
  2544. {
  2545.  if (strcmp(taskP.taskFrFunc(TP_mcps_data_request),"csmacaCallBack") == 0)
  2546.   strcpy(taskP.taskFrFunc(TP_mcps_data_request),"PD_DATA_confirm");
  2547. }
  2548. else if (taskP.taskStatus(TP_mlme_associate_response))
  2549. {
  2550.  if (strcmp(taskP.taskFrFunc(TP_mlme_associate_response),"csmacaCallBack") == 0)
  2551.   strcpy(taskP.taskFrFunc(TP_mlme_associate_response),"PD_DATA_confirm");
  2552.  //else //other commands using indirect transmission (may  be none): TBD
  2553. }
  2554. txCsmaca = pendPkt;
  2555. plme_set_trx_state_request(p_TX_ON);
  2556. }
  2557. else
  2558. {
  2559. csmacaResume();
  2560. }
  2561. }
  2562. //else //may need to send a zero-length packet in implementation
  2563. }
  2564. else if (wph->MSDU_CmdType == 0x08) //Coordinator realignment
  2565. {
  2566. mpib.macPANId = *((UINT_16 *)wph->MSDU_Payload);
  2567. mpib.macCoordShortAddress = *((UINT_16 *)wph->MSDU_Payload + 2);
  2568. tmp_ppib.phyCurrentChannel = wph->MSDU_Payload[4];
  2569. phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
  2570. mpib.macShortAddress = *((UINT_16 *)wph->MSDU_Payload + 5);
  2571. dispatch(p_SUCCESS,__FUNCTION__);
  2572. }
  2573. Packet::free(rxCmd); //we logged the command packet before, here just free it
  2574. rxCmd = 0;
  2575. }
  2576. else if (rxData)
  2577. {
  2578. wph = HDR_LRWPAN(rxData);
  2579. ch = HDR_CMN(rxData);
  2580. frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
  2581. frmCtrl.parse();
  2582. if (taskP.taskStatus(TP_mlme_poll_request))
  2583. dispatch(p_SUCCESS,__FUNCTION__,p_SUCCESS,status);
  2584. //else //do nothing
  2585. //the data waiting timer in data polling expired and the upper layer confirmed
  2586. //with a status NO_DATA -- but we see no reason not to continue passing this data
  2587. //packet to upper layer (note that the ack. has already been sent to data source -- 
  2588. //we shouldn't drop the data packet here).
  2589. //strip off the MAC sublayer header
  2590. ch->size() -= macHeaderLen(wph->MHR_FrmCtrl);
  2591. MCPS_DATA_indication(frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.panID,wph->MHR_SrcAddrInfo.addr_64,
  2592.       frmCtrl.dstAddrMode,wph->MHR_DstAddrInfo.panID,wph->MHR_DstAddrInfo.addr_64,
  2593.       ch->size(),rxData,wph->ppduLinkQuality,
  2594.       wph->SecurityUse,wph->ACLEntry);
  2595. rxData = 0;
  2596. }
  2597. }
  2598. void Mac802_15_4::backoffBoundHandler(void)
  2599. {
  2600. if (!beaconWaiting)
  2601. if (txAck) //<txAck> may have been cancelled by <macBeaconRxTimer>
  2602. {
  2603. #ifdef DEBUG802_15_4
  2604. fprintf(stdout,"[%s::%s][%f](node %d) transmit M_ACK to %d: SN = %d, uid = %d, mac_uid = %ldn",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macDA(txAck),HDR_LRWPAN(txAck)->MHR_BDSN,HDR_CMN(txAck)->uid(),HDR_LRWPAN(txAck)->uid);
  2605. #endif
  2606. txPkt = txAck;
  2607. HDR_CMN(txAck)->direction() = hdr_cmn::DOWN;
  2608. sendDown(txAck->refcopy(), this);
  2609. }
  2610. }
  2611. // End of file: p802_15_4mac.cc