ssscheduler.cc
上传用户:hzie11
上传日期:2013-10-07
资源大小:1487k
文件大小:47k
源码类别:

网络

开发平台:

C/C++

  1. /* This software was developed at the National Institute of Standards and
  2.  * Technology by employees of the Federal Government in the course of
  3.  * their official duties. Pursuant to title 17 Section 105 of the United
  4.  * States Code this software is not subject to copyright protection and
  5.  * is in the public domain.
  6.  * NIST assumes no responsibility whatsoever for its use by other parties,
  7.  * and makes no guarantees, expressed or implied, about its quality,
  8.  * reliability, or any other characteristic.
  9.  * <BR>
  10.  * We would appreciate acknowledgement if the software is used.
  11.  * <BR>
  12.  * NIST ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
  13.  * DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
  14.  * FROM THE USE OF THIS SOFTWARE.
  15.  * </PRE></P>
  16.  * @author  rouil
  17.  */
  18. #include "ssscheduler.h"
  19. #include "burst.h"
  20. /**
  21.  * Tcl hook for creating SS scheduler 
  22.  */
  23. static class SSschedulerClass : public TclClass {
  24. public:
  25.   SSschedulerClass() : TclClass("WimaxScheduler/SS") {}
  26.   TclObject* create(int, const char*const*) {
  27.     return (new SSscheduler());
  28.     
  29.   }
  30. } class_ssscheduler;
  31. /*
  32.  * Create a scheduler
  33.  */
  34. SSscheduler::SSscheduler (): t1timer_(0),t2timer_(0),t6timer_(0), t12timer_(0),
  35.      t21timer_(0), lostDLMAPtimer_(0), lostULMAPtimer_(0),
  36.      t44timer_(0), scan_info_(0)
  37. {
  38.   debug2 ("SSscheduler createdn");
  39. }
  40. /**
  41.  * Initializes the scheduler
  42.  */
  43. void SSscheduler::init ()
  44. {
  45.   WimaxScheduler::init();
  46.   
  47.   //At initialization, the SS is looking for synchronization
  48.   mac_->setMacState (MAC802_16_WAIT_DL_SYNCH);
  49.   mac_->getPhy()->setMode (OFDM_RECV);
  50.   //start timer for expiration
  51.   t21timer_ = new WimaxT21Timer (mac_);
  52.   t21timer_->start (mac_->macmib_.t21_timeout);
  53.   //creates other timers
  54.   t1timer_ = new WimaxT1Timer (mac_);
  55.   t12timer_ = new WimaxT12Timer (mac_);
  56.   t2timer_ = new WimaxT2Timer (mac_);
  57.   lostDLMAPtimer_ = new WimaxLostDLMAPTimer (mac_);
  58.   lostULMAPtimer_ = new WimaxLostULMAPTimer (mac_);
  59.   nb_scan_req_ = 0;
  60.   scan_info_ = (struct scanning_structure *) malloc (sizeof (struct scanning_structure));
  61.   memset (scan_info_, 0, sizeof (struct scanning_structure));
  62.   scan_info_->nbr = NULL;
  63.   scan_info_->substate = NORMAL;
  64. }
  65. /**
  66.  * Interface with the TCL script
  67.  * @param argc The number of parameter
  68.  * @param argv The list of parameters
  69.  */
  70. int SSscheduler::command(int argc, const char*const* argv)
  71. {
  72.   if (argc == 2) {
  73.     if (strcmp(argv[1], "send-scan") == 0) {
  74.       send_scan_request();
  75.       return TCL_OK;
  76.     }
  77.   }
  78.   
  79.   return TCL_ERROR;
  80. }
  81. /**
  82.  * Start a new frame
  83.  */
  84. void SSscheduler::start_dlsubframe ()
  85. {
  86.   //mac_->debug ("At %f in Mac %d SS scheduler dlsubframe expires %dn", NOW, mac_->addr(), scan_info_->substate);
  87.   mac_->frame_number_++;
  88.   switch (scan_info_->substate) {
  89.   case SCAN_PENDING: 
  90.     if (scan_info_->count == 0) {
  91.       resume_scanning();
  92.       return;
  93.     } 
  94.     scan_info_->count--;
  95.     break;
  96.   case HANDOVER_PENDING:
  97.     if (scan_info_->handoff_timeout == 0) {
  98.       assert (scan_info_->nbr);
  99. #ifdef USE_802_21
  100.       mac_->debug ("At %f in Mac %d link handoff proceedingn", NOW, mac_->addr());
  101.       mac_->send_link_handoff_proceeding (mac_->addr(), mac_->getPeerNode_head()->getPeerNode(), scan_info_->nbr->getID());
  102. #endif 
  103.       scan_info_->substate = HANDOVER;
  104.       //restore previous state 
  105.       //mac_->restore_state (scan_info_->nbr->getState()->state_info);
  106.       mac_->setChannel (scan_info_->nbr->getState()->state_info->channel);
  107.       lost_synch ();
  108.       //add target as peer
  109.       mac_->addPeerNode (new PeerNode(scan_info_->nbr->getID()));
  110.       return;
  111.     }
  112.     scan_info_->handoff_timeout--;
  113.     break;
  114.   default:
  115.     break;
  116.   }
  117.     
  118.   //change state of PHY
  119.   //mac_->getPhy()->setMode (OFDM_RECV);
  120.   
  121.   //this is the begining of new frame
  122.   map_->setStarttime (NOW);
  123.   //start handler of dlsubframe
  124.   map_->getDlSubframe()->getTimer()->sched (0);
  125.   //reschedule for next frame
  126.   dl_timer_->resched (mac_->getFrameDuration());
  127. }
  128. /**
  129.  * Start a new frame
  130.  */
  131. void SSscheduler::start_ulsubframe ()
  132. {
  133.   //mac_->debug ("At %f in Mac %d SS scheduler ulsubframe expiresn", NOW, mac_->addr());
  134.   
  135.   //change state of PHY: even though it should have been done before
  136.   //there are some cases where it does not (during scanning)
  137.   mac_->getPhy()->setMode (OFDM_SEND);
  138.   //1-Transfert the packets from the queues in Connections to burst queues
  139.   Burst *b;
  140.   OFDMPhy *phy = mac_->getPhy();
  141.   //printf ("SS has %d ul burstsn", map_->getUlSubframe()->getNbPdu ());
  142.   PeerNode *peer = mac_->getPeerNode_head(); //this is the BS
  143.   assert (peer!=NULL);
  144.   for (int index = 0 ; index < map_->getUlSubframe()->getNbPdu (); index++) {
  145.     b = map_->getUlSubframe()->getPhyPdu (index)->getBurst (0);
  146.     if (b->getIUC()==UIUC_END_OF_MAP) {
  147.       //consistency check..
  148.       assert (index == map_->getUlSubframe()->getNbPdu ()-1);
  149.       break;
  150.     }    
  151.     
  152.     if (b->getIUC()==UIUC_INITIAL_RANGING || b->getIUC()==UIUC_REQ_REGION_FULL)
  153.       continue;
  154.     int duration = 0; 
  155.     //get the packets from the connection with the same CID
  156.     //printf ("tBurst CID=%dn", b->getCid());
  157.     Connection *c=mac_->getCManager ()->get_connection (b->getCid(), true);
  158.     //assert (c);
  159.     if (!c)
  160.       continue; //I do not have this CID. Must be for another node
  161.     //transfert the packets until it reaches burst duration or no more packets
  162.     assert (c->getType()==CONN_PRIMARY);
  163.     if (peer->getBasic()!= NULL) 
  164.       duration = transfer_packets (peer->getBasic(), b, duration);
  165.     if (peer->getPrimary()!= NULL)
  166.       duration = transfer_packets (peer->getPrimary(), b, duration);
  167.     if (peer->getSecondary()!= NULL)
  168.       duration = transfer_packets (peer->getSecondary(), b, duration);
  169.     if (peer->getOutData()!=NULL)
  170.       duration = transfer_packets (peer->getOutData(), b, duration);
  171.   }
  172.   //2-compute size of data left to create bandwidth requests
  173.   if (peer->getBasic()!= NULL) 
  174.     create_request (peer->getBasic());
  175.   if (peer->getPrimary()!= NULL)
  176.     create_request (peer->getPrimary());
  177.   if (peer->getSecondary()!= NULL)
  178.     create_request (peer->getSecondary());
  179.   if (peer->getOutData()!=NULL)
  180.     create_request (peer->getOutData());
  181.   //start handler for ulsubframe
  182.   b = map_->getUlSubframe()->getPhyPdu (0)->getBurst (0);
  183.   map_->getUlSubframe()->getTimer()->sched (b->getStarttime()*phy->getSymbolTime());
  184.   //reschedule for next frame
  185.   ul_timer_->resched (mac_->getFrameDuration());      
  186. }
  187. /**
  188.  * Create a request for the given connection
  189.  * @param con The connection to check
  190.  */
  191. void SSscheduler::create_request (Connection *con)
  192. {
  193.   if (con->queueLength()==0)
  194.     return; //queue is empty
  195.   else if (map_->getUlSubframe()->getBw_req()->getRequest (con->get_cid())!=NULL) {
  196.     debug2 ("At %f in Mac %d already pending requests for cid=%dn", NOW, mac_->addr(), con->get_cid());
  197.     return; //there is already a pending request
  198.   }
  199.   Packet *p= mac_->getPacket();
  200.   hdr_cmn* ch = HDR_CMN(p);
  201.   bw_req_header_t *header = (bw_req_header_t *)&(HDR_MAC802_16(p)->header);
  202.   header->ht=1;
  203.   header->ec=1;
  204.   header->type = 0; //incremental..to check meaning
  205.   header->br = con->queueByteLength();
  206.   header->cid = con->get_cid();
  207.   double txtime = mac_->getPhy()->getTrxTime (ch->size(), map_->getUlSubframe()->getProfile (UIUC_REQ_REGION_FULL)->getEncoding());
  208.   ch->txtime() = txtime;
  209.   map_->getUlSubframe()->getBw_req()->addRequest (p, con->get_cid(), con->queueByteLength());
  210.   debug2 ("SSscheduler enqueued request for cid=%d len=%dn", con->get_cid(), con->queueByteLength());
  211.   //start timeout for request
  212. }
  213. /**
  214.  * Process a packet received by the Mac. Only scheduling related packets should be sent here (BW request, UL_MAP...)
  215.  * @param p The packet to process
  216.  */
  217. void SSscheduler::process (Packet * p)
  218. {
  219.   assert (mac_ && HDR_CMN(p)->ptype()==PT_MAC);
  220.   debug2 ("SSScheduler received packet to processn");
  221.   
  222.   hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(p);
  223.   gen_mac_header_t header = wimaxHdr->header;
  224.   //we cast to this frame because all management frame start with
  225.   //a type 
  226.   mac802_16_dl_map_frame *frame = (mac802_16_dl_map_frame*) p->accessdata();
  227.   switch (frame->type) {
  228.   case MAC_DL_MAP: 
  229.     map_->setStarttime (NOW-HDR_CMN(p)->txtime());
  230.     //printf ("At %f frame start at %fn", NOW, map_->getStarttime());
  231.     process_dl_map (frame);
  232.     break;
  233.   case MAC_DCD: 
  234.     process_dcd ((mac802_16_dcd_frame*)frame);
  235.     break;
  236.   case MAC_UL_MAP: 
  237.     process_ul_map ((mac802_16_ul_map_frame*)frame);
  238.     break;
  239.   case MAC_UCD: 
  240.     process_ucd ((mac802_16_ucd_frame*)frame);
  241.     break;
  242.   case MAC_RNG_RSP:
  243.     process_ranging_rsp ((mac802_16_rng_rsp_frame*) frame);
  244.     break;
  245.   case MAC_REG_RSP:
  246.     process_reg_rsp ((mac802_16_reg_rsp_frame*) frame);
  247.     break;    
  248.   case MAC_MOB_SCN_RSP:
  249.     process_scan_rsp ((mac802_16_mob_scn_rsp_frame *) frame);
  250.     break;
  251.   case MAC_MOB_BSHO_RSP:
  252.     process_bsho_rsp ((mac802_16_mob_bsho_rsp_frame *) frame);
  253.     break;
  254.   case MAC_MOB_NBR_ADV:
  255.     process_nbr_adv ((mac802_16_mob_nbr_adv_frame *) frame);
  256.     break;
  257.   default:
  258.     mac_->debug ("unknown packet in SS %dn", mac_->addr());
  259.     //exit (0);
  260.   }
  261.   Packet::free (p);
  262. }
  263. /**
  264.  * Return the type of STA this scheduler is good for
  265.  * @return STA_SS
  266.  */
  267. station_type_t SSscheduler::getNodeType ()
  268. {
  269.   return STA_MN;
  270. }
  271. /**
  272.  * Called when lost synchronization
  273.  */
  274. void SSscheduler::lost_synch ()
  275. {
  276.   //reset timers
  277.   if (t1timer_->busy()!=0)
  278.     t1timer_->stop();
  279.   if (t12timer_->busy()!=0)
  280.     t12timer_->stop();
  281.   if (t21timer_->busy()!=0)
  282.     t21timer_->stop();
  283.   if (lostDLMAPtimer_->busy()!=0)
  284.     lostDLMAPtimer_->stop(); 
  285.   if (lostULMAPtimer_->busy()!=0)
  286.     lostULMAPtimer_->stop(); 
  287.   if (t2timer_->busy()!=0)
  288.     t2timer_->stop(); 
  289.   if (t44timer_ && t44timer_->busy()!=0)
  290.     t44timer_->stop();
  291.   //we need to go to receiving mode
  292.   //printf ("Set phy to recv %xn", mac_->getPhy());
  293.   mac_->getPhy()->setMode (OFDM_RECV);
  294.   if (mac_->getMacState()==MAC802_16_CONNECTED) {
  295.     //remove possible pending requests
  296.     map_->getUlSubframe()->getBw_req()->removeRequests(); 
  297. #ifdef USE_802_21
  298.     mac_->debug ("At %f in Mac %d, send link downn", NOW, mac_->addr());
  299.     mac_->send_link_down (mac_->addr(), RC_FAIL_NORESOURCE);
  300. #endif
  301.   }
  302.   //remove information about peer node
  303.   if (mac_->getPeerNode_head())
  304.     mac_->removePeerNode (mac_->getPeerNode_head());
  305.   //start waiting for DL synch
  306.   mac_->setMacState (MAC802_16_WAIT_DL_SYNCH);
  307.   t21timer_->start (mac_->macmib_.t21_timeout);
  308.   if (dl_timer_->status()==TIMER_PENDING)
  309.     dl_timer_->cancel();
  310.   map_->getDlSubframe()->getTimer()->reset();
  311.   if (ul_timer_->status()==TIMER_PENDING)
  312.     ul_timer_->cancel();
  313.   map_->getUlSubframe()->getTimer()->reset();
  314. }
  315.  
  316. /**
  317.  * Called when a timer expires
  318.  * @param The timer ID
  319.  */
  320. void SSscheduler::expire (timer_id id)
  321. {
  322.   switch (id) {
  323.   case WimaxT21TimerID:
  324.     mac_->debug ("At %f in Mac %d, synchronization failedn", NOW, mac_->addr());
  325.     //go to next channel
  326.     mac_->nextChannel();
  327.     t21timer_->start (mac_->macmib_.t21_timeout);
  328.     break;
  329.   case WimaxLostDLMAPTimerID:
  330.     mac_->debug ("At %f in Mac %d, lost synchronization (DL_MAP)n", NOW, mac_->addr());
  331.     lost_synch ();
  332.     break;
  333.   case WimaxT1TimerID:
  334.     mac_->debug ("At %f in Mac %d, lost synchronization (DCD)n", NOW, mac_->addr());
  335.     lost_synch ();
  336.     break;
  337.   case WimaxLostULMAPTimerID:
  338.     mac_->debug ("At %f in Mac %d, lost synchronization (UL_MAP)n", NOW, mac_->addr());
  339.     lost_synch ();
  340.     break;
  341.   case WimaxT12TimerID:
  342.     mac_->debug ("At %f in Mac %d, lost uplink param (UCD)n", NOW, mac_->addr());
  343.     lost_synch ();
  344.     break;
  345.   case WimaxT2TimerID:
  346.     mac_->debug ("At %f in Mac %d, lost synchronization (RNG)n", NOW, mac_->addr());
  347.     map_->getUlSubframe()->getRanging()->removeRequest ();
  348.     lost_synch ();
  349.     break;
  350.   case WimaxT3TimerID:
  351.     mac_->debug ("At %f in Mac %d, no response from BSn", NOW, mac_->addr());
  352.     //we reach the maximum number of retries
  353.     //mark DL channel usuable (i.e we go to next)
  354.     map_->getUlSubframe()->getRanging()->removeRequest ();
  355.     mac_->nextChannel();
  356.     lost_synch ();
  357.     break;
  358.   case WimaxT6TimerID:
  359.     mac_->debug ("At %f in Mac %d, registration timeout (nbretry=%d)n", NOW, mac_->addr(),
  360.  nb_reg_retry_);
  361.     if (nb_reg_retry_ == mac_->macmib_.reg_req_retry) {
  362.       mac_->debug ("tmax retry excedeedn");
  363.       lost_synch ();
  364.     } else {
  365.       send_registration();
  366.     }
  367.     break;
  368.   case WimaxT44TimerID:
  369.     mac_->debug ("At %f in Mac %d, did not receive MOB_SCN-RSP (nb_retry=%d)n", NOW, mac_->addr(), nb_scan_req_);
  370.     if (nb_scan_req_ <= mac_->macmib_.scan_req_retry) {
  371.       send_scan_request ();
  372.     } else { //reset for next time
  373.       nb_scan_req_ = 0;
  374.     }
  375.     break;
  376.   case WimaxScanIntervalTimerID:
  377.     pause_scanning ();
  378.     break;    
  379.   case WimaxRdvTimerID:
  380.     //we need to meet at another station. We cancel the current scanning
  381.     //lost_synch ();
  382.     mac_->debug ("At %f in Mac %d Rdv timer expiredn", NOW, mac_->addr());
  383.     break;
  384.   default:
  385.     mac_->debug ("Trigger unkownn");
  386.   }
  387. }
  388. /**** Packet processing methods ****/
  389. /**
  390.  * Process a DL_MAP message
  391.  * @param frame The dl_map information
  392.  */
  393. void SSscheduler::process_dl_map (mac802_16_dl_map_frame *frame)
  394. {
  395.   assert (frame);
  396.   
  397.   //create an entry for the BS
  398.   if (mac_->getPeerNode (frame->bsid)==NULL)
  399.     mac_->addPeerNode (new PeerNode (frame->bsid));
  400.   map_->parseDLMAPframe (frame);
  401.   if (mac_->getMacState()==MAC802_16_WAIT_DL_SYNCH) {
  402.     mac_->debug ("At %f in %d, received DL_MAP for synch from %d (substate=%d)n", 
  403.  NOW, mac_->addr(), frame->bsid,scan_info_->substate);
  404.     assert (t21timer_->busy()!=0);
  405.     //synchronization is done
  406.     t21timer_->stop();
  407.     //start lost_dl_map
  408.     lostDLMAPtimer_->start (mac_->macmib_.lost_dlmap_interval);
  409.     //start T1: DCD
  410.     t1timer_->start (mac_->macmib_.t1_timeout);
  411.     //start T12: UCD
  412.     t12timer_->start (mac_->macmib_.t12_timeout);
  413. #ifdef USE_802_21
  414.     mac_->debug ("At %f in Mac %d, send link detectedn", NOW, mac_->addr());
  415.     mac_->send_link_detected (mac_->addr(), frame->bsid, 1);
  416. #endif
  417.     
  418.     mac_->setMacState(MAC802_16_WAIT_DL_SYNCH_DCD);
  419.     //if I am doing handoff and we have dcd/ucd information 
  420.     //from scanning, use it
  421.     if (scan_info_->substate == HANDOVER || scan_info_->substate == SCANNING) {
  422.       if (scan_info_->substate == SCANNING) {
  423. if (scan_info_->nbr == NULL || scan_info_->nbr->getID()!=frame->bsid) {
  424.   //check if an entry already exist in the database
  425.   scan_info_->nbr = nbr_db_->getNeighbor (frame->bsid);
  426.   if (scan_info_->nbr == NULL) {
  427.     //create entry
  428.     debug2 ("Creating nbr info for node %dn", frame->bsid);
  429.     scan_info_->nbr = new NeighborEntry (frame->bsid);
  430.     nbr_db_->addNeighbor (scan_info_->nbr);
  431.   } else {
  432.     debug2 ("loaded nbr infon");
  433.     if (scan_info_->nbr->isDetected ()) {
  434.         //we already synchronized with this AP...skip channel
  435.         mac_->nextChannel();
  436.         lost_synch ();
  437.         return;
  438.       } 
  439.   }
  440. }
  441.       }//if HANDOVER, scan_info_->nbr is already set
  442.       bool error = false;
  443.       //we check if we can read the DL_MAP
  444.       mac802_16_dcd_frame *dcd = scan_info_->nbr->getDCD();
  445.       if (dcd!=NULL) {
  446. debug2 ("Check if we can decode stored dcdn");
  447. //check if we can decode dl_map with previously acquired dcd      
  448. bool found;
  449. for (int i = 0 ; !error && i < map_->getDlSubframe()->getPdu()->getNbBurst() ; i++) {
  450.   int diuc = map_->getDlSubframe()->getPdu()->getBurst(i)->getIUC();
  451.   if (diuc == DIUC_END_OF_MAP)
  452.     continue;
  453.   found = false;
  454.   for (u_int32_t j = 0 ; !found && j < dcd->nb_prof; j++) {
  455.     found = dcd->profiles[j].diuc==diuc;     
  456.   }
  457.   error = !found;
  458. }
  459. if (!error)
  460.   process_dcd (dcd);
  461.       } else {
  462. debug2 ("No DCD information foundn");
  463.       }
  464.     }
  465.   } else {
  466.     //maintain synchronization
  467.     assert (lostDLMAPtimer_->busy());
  468.     lostDLMAPtimer_->stop();
  469.     //printf ("update dlmap timern");
  470.     lostDLMAPtimer_->start (mac_->macmib_.lost_dlmap_interval);
  471.     if (mac_->getMacState()!= MAC802_16_WAIT_DL_SYNCH_DCD
  472. && mac_->getMacState()!=MAC802_16_UL_PARAM) {
  473.       //since the map may have changed, we need to adjust the timer 
  474.       //for the DLSubframe
  475.       double stime = map_->getStarttime();
  476.       stime += map_->getDlSubframe()->getPdu()->getBurst(1)->getStarttime()*mac_->getPhy()->getSymbolTime();
  477.       //printf ("received dl..needs to update expiration to %f, %f,%fn", stime, NOW,map_->getStarttime());
  478.       map_->getDlSubframe()->getTimer()->resched (stime-NOW);
  479.       dl_timer_->resched (map_->getStarttime()+mac_->getFrameDuration()-NOW);
  480.     }
  481.   }
  482. }
  483. /**
  484.  * Process a DCD message
  485.  * @param frame The dcd information
  486.  */
  487. void SSscheduler::process_dcd (mac802_16_dcd_frame *frame)
  488. {
  489.   if (mac_->getMacState()==MAC802_16_WAIT_DL_SYNCH) {
  490.     //we are waiting for DL_MAP, ignore this message
  491.     return;
  492.   }
  493.   map_->parseDCDframe (frame);
  494.   if (mac_->getMacState()==MAC802_16_WAIT_DL_SYNCH_DCD) {
  495.     mac_->debug ("At %f in %d, received DCD for synchn", NOW, mac_->addr());
  496.     //now I have all information such as frame duration
  497.     //adjust timing in case the frame we received the DL_MAP
  498.     //and the DCD is different
  499.     while (NOW - map_->getStarttime () > mac_->getFrameDuration()) {
  500.       map_->setStarttime (map_->getStarttime()+mac_->getFrameDuration());
  501.     }
  502.     
  503.     //store information to be used during potential handoff
  504.     if (scan_info_->substate == SCANNING) {
  505.       mac802_16_dcd_frame *tmp = (mac802_16_dcd_frame *) malloc (sizeof (mac802_16_dcd_frame));
  506.       memcpy (tmp, frame, sizeof (mac802_16_dcd_frame));
  507.       mac802_16_dcd_frame *old = scan_info_->nbr->getDCD(); 
  508.       if (frame == old)
  509. frame = tmp;
  510.       if (old)
  511. free (old); //free previous entry
  512.       scan_info_->nbr->setDCD(tmp);    //set new one
  513.     }
  514.     mac_->setMacState(MAC802_16_UL_PARAM);
  515.     //we can schedule next frame
  516.     //printf ("SS schedule next frame at %fn", map_->getStarttime()+mac_->getFrameDuration());
  517.     //dl_timer_->sched (map_->getStarttime()+mac_->getFrameDuration()-NOW);
  518.   }
  519.   if (t1timer_->busy()!=0) {
  520.     //we were waiting for this packet
  521.     t1timer_->stop();
  522.     t1timer_->start (mac_->macmib_.t1_timeout);
  523.   }
  524. }
  525. /**
  526.  * Process a UCD message
  527.  * @param frame The ucd information
  528.  */
  529. void SSscheduler::process_ucd (mac802_16_ucd_frame *frame)
  530. {
  531.   if (mac_->getMacState()==MAC802_16_WAIT_DL_SYNCH
  532.       ||mac_->getMacState()==MAC802_16_WAIT_DL_SYNCH_DCD) {
  533.     //discard the packet
  534.     return;
  535.   }
  536.   assert (t12timer_->busy()!=0); //we are waiting for this packet
  537.   if (mac_->getMacState()==MAC802_16_UL_PARAM) {
  538.     //check if uplink channel usable
  539.     mac_->debug ("At %f in %d, received UL(UCD) parametersn", NOW, mac_->addr());
  540.     //start T2: ranging
  541.     t2timer_->start (mac_->macmib_.t2_timeout);
  542.     //start Lost UL-MAP
  543.     lostULMAPtimer_->start (mac_->macmib_.lost_ulmap_interval);
  544.     //store information to be used during potential handoff
  545.     if (scan_info_->substate == SCANNING) {
  546.       mac802_16_ucd_frame *tmp = (mac802_16_ucd_frame *) malloc (sizeof (mac802_16_ucd_frame));
  547.       memcpy (tmp, frame, sizeof (mac802_16_ucd_frame));
  548.       mac802_16_ucd_frame *old = scan_info_->nbr->getUCD(); 
  549.       if (frame == old)
  550. frame = tmp;
  551.       if (old) 
  552. free (old); //free previous entry
  553.       scan_info_->nbr->setUCD(tmp);    //set new one            
  554.       
  555.     }
  556.     //change state
  557.     mac_->setMacState (MAC802_16_RANGING);
  558.   }
  559.   //reset T12
  560.   t12timer_->stop();
  561.   t12timer_->start (mac_->macmib_.t12_timeout);
  562.   map_->parseUCDframe (frame);
  563. }
  564. /**
  565.  * Process a UL_MAP message
  566.  * @param frame The ul_map information
  567.  */
  568. void SSscheduler::process_ul_map (mac802_16_ul_map_frame *frame)
  569. {
  570.   if (mac_->getMacState()==MAC802_16_WAIT_DL_SYNCH 
  571.       || mac_->getMacState()==MAC802_16_WAIT_DL_SYNCH_DCD) {
  572.     //discard the packet
  573.     return;
  574.   }
  575.   if (mac_->getMacState()==MAC802_16_UL_PARAM) {
  576.     if (scan_info_->substate == HANDOVER || scan_info_->substate==SCANNING) {
  577.       FrameMap *tmpMap = new FrameMap (mac_);
  578.       tmpMap->parseULMAPframe (frame); 
  579.       //printf ("Checking if we can read UL_MAPn");
  580.       bool error = false;
  581.       //we check if we can read the UL_MAP
  582.       mac802_16_ucd_frame *ucd = scan_info_->nbr->getUCD();
  583.       if (ucd!=NULL) {
  584. //check if we can decode ul_map with previously acquired ucd      
  585. bool found;
  586. for (int i = 0 ; !error && i < tmpMap->getUlSubframe()->getNbPdu() ; i++) {
  587.   UlBurst *b = (UlBurst*)tmpMap->getUlSubframe()->getPhyPdu(i)->getBurst(0);
  588.   int uiuc = b->getIUC();
  589.   if (uiuc == UIUC_END_OF_MAP)
  590.     continue;
  591.   if (uiuc == UIUC_EXT_UIUC && b->getExtendedUIUC ()== UIUC_FAST_RANGING)
  592.       uiuc = b->getFastRangingUIUC();   
  593.   found = false;
  594.   for (u_int32_t j = 0 ; !found && j < ucd->nb_prof; j++) {
  595.     //printf ("t prof=%d, search=%dn", ucd->profiles[j].uiuc, uiuc);
  596.     found = ucd->profiles[j].uiuc==uiuc;     
  597.   }
  598.   error = !found;
  599. }
  600. if (!error)
  601.   process_ucd (ucd);
  602.       }
  603.       delete (tmpMap);
  604.       if (error) {
  605. //we cannot read message
  606. return;
  607.       }
  608.     } else
  609.       return;
  610.   }
  611.   if (scan_info_->substate == SCANNING) {
  612.     //TBD: add checking scanning type for the given station
  613.     u_char scanning_type = 0;
  614.     for (int i = 0 ; i < scan_info_->rsp->n_recommended_bs_full ; i++) {
  615.       if (scan_info_->rsp->rec_bs_full[i].recommended_bs_id == scan_info_->nbr->getID()) {
  616. scanning_type = scan_info_->rsp->rec_bs_full[i].scanning_type;
  617. break;
  618.       }
  619.     }
  620.     if (scanning_type == 0) {
  621.       //store information about possible base station and keep scanning
  622.       scan_info_->nbr->getState()->state_info= mac_->backup_state();
  623.       mac_->debug ("At %f in Mac %d bs %d detected during scanningn", NOW, mac_->addr(), scan_info_->nbr->getID());
  624.       scan_info_->nbr->setDetected (true);
  625.       mac_->nextChannel();
  626.       lost_synch ();
  627.       return;
  628.     }
  629.   }
  630.   map_->parseULMAPframe (frame);  
  631.   if (mac_->getMacState()==MAC802_16_RANGING) {
  632.       //execute ranging
  633.      assert (t2timer_->busy()!=0); //we are waiting for this packet
  634.      init_ranging ();
  635.   }
  636.   //schedule when to take care of outgoing packets
  637.   double start = map_->getStarttime();
  638.   start += map_->getUlSubframe()->getStarttime()*mac_->getPhy()->getPS(); //offset for ul subframe
  639.   start -= NOW; //works with relative time not absolute
  640.   debug2 ("Uplink starts in %f (framestate=%f) %f %fn", 
  641.   start, 
  642.   map_->getStarttime(),
  643.   mac_->getFrameDuration()/mac_->getPhy()->getPS(), 
  644.   mac_->getFrameDuration()/mac_->getPhy()->getSymbolTime());
  645.   
  646.   ul_timer_->resched (start);
  647.   //reset Lost UL-Map
  648.   lostULMAPtimer_->stop();
  649.   lostULMAPtimer_->start (mac_->macmib_.lost_ulmap_interval);
  650. }
  651. /**
  652.  * Process a ranging response message 
  653.  * @param frame The ranging response frame
  654.  */
  655. void SSscheduler::process_ranging_rsp (mac802_16_rng_rsp_frame *frame)
  656. {
  657.   //check the destination
  658.   if (frame->ss_mac_address != mac_->addr())
  659.     return;
  660.   
  661.   Connection *basic, *primary;
  662.   PeerNode *peer;
  663.   //TBD: add processing for periodic ranging
  664.   //check status 
  665.   switch (frame->rng_status) {
  666.   case RNG_SUCCESS:
  667.     mac_->debug ("Ranging response: status = Success.Basic=%d, Primary=%dn",
  668.     frame->basic_cid, frame->primary_cid);
  669.     peer = mac_->getPeerNode_head();
  670.     assert (peer);
  671.     map_->getUlSubframe()->getRanging()->removeRequest ();
  672.     if (scan_info_->substate == SCANNING) {
  673.       //store information about possible base station and keep scanning
  674.       scan_info_->nbr->getState()->state_info= mac_->backup_state();
  675.       scan_info_->nbr->setDetected (true);
  676.       //keep the information for later
  677.       mac802_16_rng_rsp_frame *tmp = (mac802_16_rng_rsp_frame *) malloc (sizeof (mac802_16_rng_rsp_frame));
  678.       memcpy (tmp, frame, sizeof (mac802_16_rng_rsp_frame));
  679.       scan_info_->nbr->setRangingRsp (tmp);
  680.       mac_->nextChannel();
  681.       lost_synch ();
  682.       return;
  683.     }
  684.     //ranging worked, now we must register
  685.     basic = peer->getBasic();
  686.     primary = peer->getPrimary();
  687.     if (basic!=NULL && basic->get_cid ()==frame->basic_cid) {
  688.       //duplicate response
  689.       assert (primary->get_cid () == frame->primary_cid);
  690.     } else {
  691.       if (basic !=NULL) {
  692. //we have been allocated new cids..clear old ones
  693. mac_->getCManager ()->remove_connection (basic);
  694. mac_->getCManager ()->remove_connection (primary);
  695. if (peer->getSecondary()!=NULL)
  696.   mac_->getCManager ()->remove_connection (peer->getSecondary());
  697. if (peer->getOutData()!=NULL)
  698.   mac_->getCManager ()->remove_connection (peer->getOutData());
  699. if (peer->getInData()!=NULL)
  700.   mac_->getCManager ()->remove_connection (peer->getInData());
  701.       } 
  702.       basic = new Connection (CONN_BASIC, frame->basic_cid);
  703.       Connection *upbasic = new Connection (CONN_BASIC, frame->basic_cid);
  704.       primary = new Connection (CONN_PRIMARY, frame->primary_cid);
  705.       Connection *upprimary = new Connection (CONN_PRIMARY, frame->primary_cid);
  706.       //a SS should only have one peer, the BS
  707.       peer->setBasic (upbasic); //set outgoing
  708.       peer->setPrimary (upprimary); //set outgoing
  709.       basic->setPeerNode (peer);
  710.       primary->setPeerNode (peer);
  711.       mac_->getCManager()->add_connection (upbasic, true);
  712.       mac_->getCManager()->add_connection (basic, false);
  713.       mac_->getCManager()->add_connection (upprimary, true);
  714.       mac_->getCManager()->add_connection (primary, false);
  715.     }
  716.     //registration must be sent using Primary Management CID
  717.     mac_->setMacState (MAC802_16_REGISTER);
  718.     //stop timeout timer
  719.     t2timer_->stop ();
  720.     nb_reg_retry_ = 0; //first time sending
  721.     send_registration();
  722.     break;
  723.   case RNG_ABORT:
  724.   case RNG_CONTINUE:
  725.   case RNG_RERANGE:
  726.     break;
  727.   default:
  728.     fprintf (stderr, "Unknown status replyn");
  729.     exit (-1);
  730.   }
  731. }
  732. /**
  733.  * Schedule a ranging
  734.  */
  735. void SSscheduler::init_ranging ()
  736. {
  737.   //check if there is a ranging opportunity
  738.   UlSubFrame *ulsubframe = map_->getUlSubframe();
  739.   DlSubFrame *dlsubframe = map_->getDlSubframe();
  740.   /* If I am doing a Handoff, check if I already associated 
  741.      with the target AP*/
  742.   if (scan_info_->substate == HANDOVER && scan_info_->nbr->getRangingRsp()!=NULL) {
  743.     mac_->debug ("At %f in Mac %d MN already executed ranging during scanningn", NOW, mac_->addr());
  744.     process_ranging_rsp (scan_info_->nbr->getRangingRsp());
  745.     return;
  746.   }
  747.   //check if there is Fast Ranging IE
  748.   for (PhyPdu *p = map_->getUlSubframe ()->getFirstPdu(); p ; p= p ->next_entry()) {
  749.     UlBurst *b = (UlBurst*) p->getBurst(0);
  750.     if (b->getIUC() == UIUC_EXT_UIUC && 
  751. b->getExtendedUIUC ()== UIUC_FAST_RANGING &&
  752. b->getFastRangingMacAddr ()==mac_->addr()) {
  753.       debug2 ("Found fast rangingn");
  754.       //we should put the ranging request in that burst
  755.       Packet *p= mac_->getPacket();
  756.       hdr_cmn* ch = HDR_CMN(p);
  757.       HDR_MAC802_16(p)->header.cid = INITIAL_RANGING_CID;
  758.       p->allocdata (sizeof (struct mac802_16_rng_req_frame));
  759.       mac802_16_rng_req_frame *frame = (mac802_16_rng_req_frame*) p->accessdata();
  760.       frame->type = MAC_RNG_REQ;
  761.       frame->dc_id = dlsubframe->getChannelID();
  762.       frame->ss_mac_address = mac_->addr();
  763.       //other elements??      
  764.       ch->size() += RNG_REQ_SIZE;
  765.       //compute when to send message
  766.       double txtime = mac_->getPhy()->getTrxTime (ch->size(), ulsubframe->getProfile (b->getFastRangingUIUC ())->getEncoding());
  767.       ch->txtime() = txtime;
  768.       //starttime+backoff
  769.       b->enqueue(p);
  770.       mac_->setMacState(MAC802_16_WAIT_RNG_RSP);
  771.       return;
  772.     }
  773.   }
  774.   for (PhyPdu *pdu = ulsubframe->getFirstPdu(); pdu ; pdu = pdu->next_entry()) {
  775.     if (pdu->getBurst(0)->getIUC()==UIUC_INITIAL_RANGING) {
  776.       mac_->debug ("At %f SS Mac %d found ranging opportunityn", NOW, mac_->addr());
  777.       Packet *p= mac_->getPacket();
  778.       hdr_cmn* ch = HDR_CMN(p);
  779.       HDR_MAC802_16(p)->header.cid = INITIAL_RANGING_CID;
  780.       p->allocdata (sizeof (struct mac802_16_rng_req_frame));
  781.       mac802_16_rng_req_frame *frame = (mac802_16_rng_req_frame*) p->accessdata();
  782.       frame->type = MAC_RNG_REQ;
  783.       frame->dc_id = dlsubframe->getChannelID();
  784.       frame->ss_mac_address = mac_->addr();
  785.       //other elements??      
  786.       ch->size() += RNG_REQ_SIZE;
  787.       //compute when to send message
  788.       double txtime = mac_->getPhy()->getTrxTime (ch->size(), ulsubframe->getProfile (pdu->getBurst(0)->getIUC())->getEncoding());
  789.       ch->txtime() = txtime;
  790.       //starttime+backoff
  791.       map_->getUlSubframe()->getRanging()->addRequest (p);
  792.       mac_->setMacState(MAC802_16_WAIT_RNG_RSP);
  793.       return;
  794.     }
  795.   }
  796. }
  797. /**
  798.  * Prepare to send a registration message
  799.  */
  800. void SSscheduler::send_registration ()
  801. {
  802.   Packet *p;
  803.   struct hdr_cmn *ch;
  804.   hdr_mac802_16 *wimaxHdr;
  805.   mac802_16_reg_req_frame *reg_frame;
  806.   PeerNode *peer;
  807.   //create packet for request
  808.   p = mac_->getPacket ();
  809.   ch = HDR_CMN(p);
  810.   wimaxHdr = HDR_MAC802_16(p);
  811.   p->allocdata (sizeof (struct mac802_16_reg_req_frame));
  812.   reg_frame = (mac802_16_reg_req_frame*) p->accessdata();
  813.   reg_frame->type = MAC_REG_REQ;
  814.   ch->size() += REG_REQ_SIZE;
  815.   peer = mac_->getPeerNode_head();  
  816.   wimaxHdr->header.cid = peer->getPrimary()->get_cid();
  817.   peer->getPrimary()->enqueue (p);
  818.   //start reg timeout
  819.   if (t6timer_==NULL) {
  820.     t6timer_ = new WimaxT6Timer (mac_);
  821.   }
  822.   t6timer_->start (mac_->macmib_.t6_timeout);
  823.   nb_reg_retry_++;
  824. }
  825. /**
  826.  * Process a registration response message 
  827.  * @param frame The registration response frame
  828.  */
  829. void SSscheduler::process_reg_rsp (mac802_16_reg_rsp_frame *frame)
  830. {
  831.   //check the destination
  832.   PeerNode *peer = mac_->getPeerNode_head();
  833.   if (frame->response == 0) {
  834.     //status OK
  835.     mac_->debug ("At %f in Mac %d, registration sucessful (nbretry=%d)n", NOW, mac_->addr(),
  836.  nb_reg_retry_);
  837.     Connection *secondary = peer->getSecondary();
  838.     if (!secondary) {
  839.       Connection *secondary = new Connection (CONN_SECONDARY, frame->sec_mngmt_cid);
  840.       Connection *upsecondary = new Connection (CONN_SECONDARY, frame->sec_mngmt_cid);
  841.       mac_->getCManager()->add_connection (upsecondary, true);
  842.       mac_->getCManager()->add_connection (secondary, false);
  843.       peer->setSecondary (upsecondary);
  844.       secondary->setPeerNode (peer);
  845.     }
  846.     //cancel timeout
  847.     t6timer_->stop ();
  848.     //update status
  849.     mac_->setMacState(MAC802_16_CONNECTED);
  850.     //we need to setup a data connection (will be moved to service flow handler)
  851.     mac_->getServiceHandler ()->sendFlowRequest (peer->getPeerNode(), true);
  852.     mac_->getServiceHandler ()->sendFlowRequest (peer->getPeerNode(), false);
  853. #ifdef USE_802_21
  854.     if (scan_info_->substate==HANDOVER) {
  855.       mac_->debug ("At %f in Mac %d link handoff completen", NOW, mac_->addr());      
  856.       mac_->send_link_handoff_complete (mac_->addr(), scan_info_->serving_bsid, peer->getPeerNode());
  857.       scan_info_->handoff_timeout = -1;
  858.     }
  859.     mac_->debug ("At %f in Mac %d, send link upn", NOW, mac_->addr());
  860.     mac_->send_link_up (mac_->addr(), peer->getPeerNode());
  861. #endif
  862.     
  863.   } else {
  864.     //status failure
  865.     mac_->debug ("At %f in Mac %d, registration failed (nbretry=%d)n", NOW, mac_->addr(),
  866.  nb_reg_retry_);
  867.     if (nb_reg_retry_ == mac_->macmib_.reg_req_retry) {
  868. #ifdef USE_802_21
  869.       if (scan_info_ && scan_info_->handoff_timeout == -2) {
  870. mac_->debug ("At %f in Mac %d link handoff failuren", NOW, mac_->addr());      
  871. mac_->send_link_handoff_failure (mac_->addr(), scan_info_->serving_bsid, peer->getPeerNode());
  872. scan_info_->handoff_timeout = -1;
  873.       }
  874. #endif
  875.       lost_synch ();
  876.     } else {
  877.       send_registration();
  878.     }
  879.   }
  880. }
  881. /**
  882.  * Send a scanning message to the serving BS
  883.  */
  884. void SSscheduler::send_scan_request ()
  885. {
  886.   Packet *p;
  887.   struct hdr_cmn *ch;
  888.   hdr_mac802_16 *wimaxHdr;
  889.   mac802_16_mob_scn_req_frame *req_frame;
  890.   PeerNode *peer;
  891.   mac_->debug ("At %f in Mac %d enqueue scan requestn", NOW, mac_->addr());
  892.   //create packet for request
  893.   p = mac_->getPacket ();
  894.   ch = HDR_CMN(p);
  895.   wimaxHdr = HDR_MAC802_16(p);
  896.   p->allocdata (sizeof (struct mac802_16_mob_scn_req_frame));
  897.   req_frame = (mac802_16_mob_scn_req_frame*) p->accessdata();
  898.   req_frame->type = MAC_MOB_SCN_REQ;
  899.   req_frame->scan_duration = mac_->macmib_.scan_duration;
  900.   req_frame->interleaving_interval = mac_->macmib_.interleaving;
  901.   req_frame->scan_iteration = mac_->macmib_.scan_iteration;
  902.   req_frame->n_recommended_bs_index = 0;
  903.   req_frame->n_recommended_bs_full = 0;
  904.   ch->size() += Mac802_16pkt::getMOB_SCN_REQ_size(req_frame);
  905.   peer = mac_->getPeerNode_head();  
  906.   wimaxHdr->header.cid = peer->getPrimary()->get_cid();
  907.   peer->getPrimary()->enqueue (p);
  908.   //start reg timeout
  909.   if (t44timer_==NULL) {
  910.     t44timer_ = new WimaxT44Timer (mac_);
  911.   }
  912.   t44timer_->start (mac_->macmib_.t44_timeout);
  913.   nb_scan_req_++;
  914. }
  915. /**
  916.  * Process a scanning response message 
  917.  * @param frame The scanning response frame
  918.  */
  919. void SSscheduler::process_scan_rsp (mac802_16_mob_scn_rsp_frame *frame)
  920. {
  921.   //PeerNode *peer = mac_->getPeerNode_head();
  922.   if (frame->scan_duration != 0) {
  923.     //scanning accepted
  924.     mac_->debug ("At %f in Mac %d, scanning accepted (dur=%d it=%d)n", NOW, mac_->addr(), frame->scan_duration,frame->scan_iteration );
  925.     //allocate data for scanning
  926.     //scan_info_ = (struct scanning_structure *) malloc (sizeof (struct scanning_structure));
  927.     //store copy of frame
  928.     
  929.     scan_info_->rsp = (struct mac802_16_mob_scn_rsp_frame *) malloc (sizeof (struct mac802_16_mob_scn_rsp_frame));
  930.     memcpy (scan_info_->rsp, frame, sizeof (struct mac802_16_mob_scn_rsp_frame));
  931.     scan_info_->iteration = 0;
  932.     scan_info_->count = frame->start_frame;
  933.     scan_info_->substate = SCAN_PENDING;
  934.     scan_info_->handoff_timeout = 0; 
  935.     scan_info_->serving_bsid = mac_->getPeerNode_head()->getPeerNode();
  936.     scan_info_->nb_rdv_timers = 0;
  937.     //mark all neighbors as not detected
  938.     for (int i = 0 ; i < nbr_db_->getNbNeighbor() ; i++) {
  939.       nbr_db_->getNeighbors()[i]->setDetected(false);
  940.     }
  941.     //schedule timer for rdv time (for now just use full)
  942.     //TBD: add rec_bs_index
  943.     mac_->debug ("tstart scan in %d frames (%f)n",frame->start_frame,NOW+frame->start_frame*mac_->getFrameDuration());
  944.     for (int i = 0 ; i < scan_info_->rsp->n_recommended_bs_full ; i++) {
  945.       if (scan_info_->rsp->rec_bs_full[i].scanning_type ==SCAN_ASSOC_LVL1 
  946.   || scan_info_->rsp->rec_bs_full[i].scanning_type==SCAN_ASSOC_LVL2) {
  947. debug2 ("Creating timer for bs=%d at time %fn", 
  948. scan_info_->rsp->rec_bs_full[i].recommended_bs_id, 
  949. NOW+mac_->getFrameDuration()*scan_info_->rsp->rec_bs_full[i].rdv_time);
  950. assert (nbr_db_->getNeighbor (scan_info_->rsp->rec_bs_full[i].recommended_bs_id));
  951. //get the channel
  952. int ch = mac_->getChannel (nbr_db_->getNeighbor (scan_info_->rsp->rec_bs_full[i].recommended_bs_id)->getDCD ()->frequency*1000);
  953. assert (ch!=-1);
  954. WimaxRdvTimer *timer = new WimaxRdvTimer (mac_, ch);
  955. scan_info_->rdv_timers[scan_info_->nb_rdv_timers++] = timer;
  956. timer->start(mac_->getFrameDuration()*scan_info_->rsp->rec_bs_full[i].rdv_time);
  957.       }
  958.     }
  959.   } else {
  960.     mac_->debug ("At %f in Mac %d, scanning deniedn", NOW, mac_->addr());
  961.     //what do I do???
  962.   }
  963.   t44timer_->stop();
  964. }
  965. /**
  966.  * Start/Continue scanning
  967.  */
  968. void SSscheduler::resume_scanning ()
  969. {
  970.   if (scan_info_->iteration == 0) 
  971.     mac_->debug ("At %f in Mac %d, starts scanningn", NOW, mac_->addr());
  972.   else 
  973.     mac_->debug ("At %f in Mac %d, resume scanningn", NOW, mac_->addr());
  974.   
  975.   scan_info_->substate = SCANNING;
  976.   //backup current state
  977.   scan_info_->normal_state.state_info = mac_->backup_state();
  978.   if (t1timer_->busy())
  979.     t1timer_->pause();
  980.   scan_info_->normal_state.t1timer = t1timer_;
  981.   if (t2timer_->busy())
  982.     t2timer_->pause();
  983.   scan_info_->normal_state.t2timer = t2timer_;
  984.   if (t6timer_->busy())
  985.     t6timer_->pause();
  986.   scan_info_->normal_state.t6timer = t6timer_;
  987.   if (t12timer_->busy())
  988.     t12timer_->pause();
  989.   scan_info_->normal_state.t12timer = t12timer_;
  990.   if (t21timer_->busy())
  991.     t21timer_->pause();
  992.   scan_info_->normal_state.t21timer = t21timer_;
  993.   if (lostDLMAPtimer_->busy())
  994.     lostDLMAPtimer_->pause();
  995.   scan_info_->normal_state.lostDLMAPtimer = lostDLMAPtimer_;
  996.   if (lostULMAPtimer_->busy())
  997.     lostULMAPtimer_->pause();
  998.   scan_info_->normal_state.lostULMAPtimer = lostULMAPtimer_;
  999.   scan_info_->normal_state.map = map_;
  1000.   if (scan_info_->iteration == 0) {
  1001.     //reset state
  1002.     t1timer_ = new WimaxT1Timer (mac_);
  1003.     t2timer_ = new WimaxT2Timer (mac_);
  1004.     t6timer_ = new WimaxT6Timer (mac_);
  1005.     t12timer_ = new WimaxT12Timer (mac_);
  1006.     t21timer_ = new WimaxT21Timer (mac_);
  1007.     lostDLMAPtimer_ = new WimaxLostDLMAPTimer (mac_);
  1008.     lostULMAPtimer_ = new WimaxLostULMAPTimer (mac_);
  1009.     
  1010.     map_ = new FrameMap (mac_);
  1011.     
  1012.     mac_->nextChannel();
  1013.     scan_info_->scn_timer_ = new WimaxScanIntervalTimer (mac_);
  1014.     //start waiting for DL synch
  1015.     mac_->setMacState (MAC802_16_WAIT_DL_SYNCH);
  1016.     t21timer_->start (mac_->macmib_.t21_timeout);
  1017.     if (dl_timer_->status()==TIMER_PENDING)
  1018.       dl_timer_->cancel();
  1019.     map_->getDlSubframe()->getTimer()->reset();
  1020.     if (ul_timer_->status()==TIMER_PENDING)
  1021.       ul_timer_->cancel();
  1022.     map_->getUlSubframe()->getTimer()->reset();
  1023.     
  1024.   }else{
  1025.     //restore where we left
  1026.     //restore previous timers
  1027.     mac_->restore_state(scan_info_->scan_state.state_info);
  1028.     t1timer_ = scan_info_->scan_state.t1timer;
  1029.     if (t1timer_->paused())
  1030.       t1timer_->resume();
  1031.     t2timer_ = scan_info_->scan_state.t2timer;
  1032.     if (t2timer_->paused())
  1033.       t2timer_->resume();
  1034.     t6timer_ = scan_info_->scan_state.t6timer;
  1035.     if (t6timer_->paused())
  1036.       t6timer_->resume();
  1037.     t12timer_ = scan_info_->scan_state.t12timer;
  1038.     if (t12timer_->paused())
  1039.       t12timer_->resume();
  1040.     t21timer_ = scan_info_->scan_state.t21timer;
  1041.     if (t21timer_->paused())
  1042.       t21timer_->resume();
  1043.     lostDLMAPtimer_ = scan_info_->scan_state.lostDLMAPtimer;
  1044.     if (lostDLMAPtimer_->paused())
  1045.       lostDLMAPtimer_->resume();
  1046.     lostULMAPtimer_ = scan_info_->scan_state.lostULMAPtimer;
  1047.     if (lostULMAPtimer_->paused())
  1048.       lostULMAPtimer_->resume();
  1049.     map_ = scan_info_->scan_state.map;
  1050.     
  1051.     mac_->getPhy()->setMode (OFDM_RECV);
  1052.     if (ul_timer_->status()==TIMER_PENDING)
  1053.       ul_timer_->cancel();
  1054.   }
  1055.   mac_->setNotify_upper (false);
  1056.   //printf ("Scan duration=%d, frameduration=%fn", scan_info_->rsp->scan_duration, mac_->getFrameDuration());
  1057.   scan_info_->scn_timer_->start (scan_info_->rsp->scan_duration*mac_->getFrameDuration());
  1058.   scan_info_->iteration++;
  1059.   
  1060. }
  1061. /**
  1062.  * Pause scanning
  1063.  */
  1064. void SSscheduler::pause_scanning ()
  1065. {
  1066.   if (scan_info_->iteration < scan_info_->rsp->scan_iteration)
  1067.     mac_->debug ("At %f in Mac %d, pause scanningn", NOW, mac_->addr());
  1068.   else 
  1069.     mac_->debug ("At %f in Mac %d, stop scanningn", NOW, mac_->addr());
  1070.   //return to normal mode
  1071.   if (scan_info_->iteration < scan_info_->rsp->scan_iteration) {
  1072.     //backup current state
  1073.     scan_info_->scan_state.state_info = mac_->backup_state();
  1074.     if (t1timer_->busy())
  1075.       t1timer_->pause();
  1076.     scan_info_->scan_state.t1timer = t1timer_;
  1077.     if (t2timer_->busy())
  1078.       t2timer_->pause();
  1079.     scan_info_->scan_state.t2timer = t2timer_;
  1080.     if (t6timer_->busy())
  1081.       t6timer_->pause();
  1082.     scan_info_->scan_state.t6timer = t6timer_;
  1083.     if (t12timer_->busy())
  1084.       t12timer_->pause();
  1085.     scan_info_->scan_state.t12timer = t12timer_;
  1086.     if (t21timer_->busy())
  1087.       t21timer_->pause();
  1088.     scan_info_->scan_state.t21timer = t21timer_;
  1089.     if (lostDLMAPtimer_->busy())
  1090.       lostDLMAPtimer_->pause();
  1091.     scan_info_->scan_state.lostDLMAPtimer = lostDLMAPtimer_;
  1092.     if (lostULMAPtimer_->busy())
  1093.       lostULMAPtimer_->pause();
  1094.     scan_info_->scan_state.lostULMAPtimer = lostULMAPtimer_;
  1095.     scan_info_->scan_state.map = map_;
  1096.     scan_info_->count = scan_info_->rsp->interleaving_interval;
  1097.   } else {
  1098.     //else scanning is over, no need to save data
  1099.     //reset timers
  1100.     if (t1timer_->busy()!=0)
  1101.       t1timer_->stop();
  1102.     delete (t1timer_);
  1103.     if (t12timer_->busy()!=0)
  1104.       t12timer_->stop();
  1105.     delete (t12timer_);
  1106.     if (t21timer_->busy()!=0)
  1107.       t21timer_->stop();
  1108.     delete (t21timer_);
  1109.     if (lostDLMAPtimer_->busy()!=0)
  1110.       lostDLMAPtimer_->stop(); 
  1111.     delete (lostDLMAPtimer_);
  1112.     if (lostULMAPtimer_->busy()!=0)
  1113.       lostULMAPtimer_->stop(); 
  1114.     delete (lostULMAPtimer_);
  1115.     if (t2timer_->busy()!=0)
  1116.       t2timer_->stop(); 
  1117.     delete (t2timer_);
  1118.   }
  1119.   //restore previous timers
  1120.   mac_->restore_state(scan_info_->normal_state.state_info);
  1121.   t1timer_ = scan_info_->normal_state.t1timer;
  1122.   if (t1timer_->paused())
  1123.     t1timer_->resume();
  1124.   t2timer_ = scan_info_->normal_state.t2timer;
  1125.   if (t2timer_->paused())
  1126.     t2timer_->resume();
  1127.   t6timer_ = scan_info_->normal_state.t6timer;
  1128.   if (t6timer_->paused())
  1129.     t6timer_->resume();
  1130.   t12timer_ = scan_info_->normal_state.t12timer;
  1131.   if (t12timer_->paused())
  1132.     t12timer_->resume();
  1133.   t21timer_ = scan_info_->normal_state.t21timer;
  1134.   if (t21timer_->paused())
  1135.     t21timer_->resume();
  1136.   lostDLMAPtimer_ = scan_info_->normal_state.lostDLMAPtimer;
  1137.   if (lostDLMAPtimer_->paused())
  1138.     lostDLMAPtimer_->resume();
  1139.   lostULMAPtimer_ = scan_info_->normal_state.lostULMAPtimer;
  1140.   if (lostULMAPtimer_->paused())
  1141.     lostULMAPtimer_->resume();
  1142.   map_ = scan_info_->normal_state.map;
  1143.   mac_->setNotify_upper (true);
  1144.   dl_timer_->resched (0);
  1145.   if (scan_info_->iteration == scan_info_->rsp->scan_iteration) {
  1146.     scan_info_->substate = NORMAL;
  1147.     /** here we check if there is a better BS **/
  1148.     send_msho_req();
  1149.     scan_info_->count--; //to avoid restarting scanning
  1150.     //delete (scan_info_);
  1151.     //scan_info_ = NULL;
  1152.   } else {
  1153.     scan_info_->substate = SCAN_PENDING;
  1154.   }
  1155. }
  1156. /**
  1157.  * Send a MSHO-REQ message to the BS
  1158.  */
  1159. void SSscheduler::send_msho_req ()
  1160. {
  1161.   Packet *p;
  1162.   struct hdr_cmn *ch;
  1163.   hdr_mac802_16 *wimaxHdr;
  1164.   mac802_16_mob_msho_req_frame *req_frame;
  1165.   double rssi;
  1166.   PeerNode *peer = mac_->getPeerNode_head();
  1167.   int nbPref = 0;
  1168.   for (int i = 0 ; i < nbr_db_->getNbNeighbor() ; i++) {
  1169.     NeighborEntry *entry = nbr_db_->getNeighbors()[i];
  1170.     if (entry->isDetected()) {
  1171.       mac_->debug ("At %f in Mac %d Found new AP %d..need to send HO messagen",NOW, mac_->addr(), entry->getID());
  1172.       nbPref++;
  1173.     }  
  1174.   }
  1175.   if (nbPref==0)
  1176.     return; //no other BS found
  1177.   //create packet for request
  1178.   p = mac_->getPacket ();
  1179.   ch = HDR_CMN(p);
  1180.   wimaxHdr = HDR_MAC802_16(p);
  1181.   p->allocdata (sizeof (struct mac802_16_mob_msho_req_frame)+nbPref*sizeof (mac802_16_mob_msho_req_bs_index));
  1182.   req_frame = (mac802_16_mob_msho_req_frame*) p->accessdata();
  1183.   memset (req_frame, 0, sizeof (mac802_16_mob_msho_req_bs_index));
  1184.   req_frame->type = MAC_MOB_MSHO_REQ;
  1185.   
  1186.   req_frame->report_metric = 0x2; //include RSSI
  1187.   req_frame->n_new_bs_index = 0;
  1188.   req_frame->n_new_bs_full = nbPref;
  1189.   req_frame->n_current_bs = 1;
  1190.   rssi = mac_->getPeerNode_head()->getStatWatch()->average();
  1191.   debug2 ("RSSI=%e, %d, bs=%dn", rssi, (u_char)((rssi+103.75)/0.25), mac_->getPeerNode_head()->getPeerNode());
  1192.   req_frame->bs_current[0].temp_bsid = mac_->getPeerNode_head()->getPeerNode();
  1193.   req_frame->bs_current[0].bs_rssi_mean = (u_char)((rssi+103.75)/0.25);
  1194.   for (int i = 0, j=0; i < nbr_db_->getNbNeighbor() ; i++) {
  1195.     NeighborEntry *entry = nbr_db_->getNeighbors()[i];
  1196.     //TBD: there is an error measuring RSSI for current BS during scanning
  1197.     //anyway, we don't put it in the least, so it's ok for now
  1198.     if (entry->isDetected() && entry->getID()!= mac_->getPeerNode_head()->getPeerNode()) {
  1199.       req_frame->bs_full[j].neighbor_bs_index = entry->getID();
  1200.       rssi = entry->getState()->state_info->peer_list->lh_first->getStatWatch()->average();
  1201.       debug2 ("RSSI=%e, %d, bs=%dn", rssi, (u_char)((rssi+103.75)/0.25), entry->getID());
  1202.       req_frame->bs_full[j].bs_rssi_mean = (u_char)((rssi+103.75)/0.25);
  1203.       //the rest of req_frame->bs_full is unused for now..
  1204.       req_frame->bs_full[j].arrival_time_diff_ind = 0;
  1205.       j++;
  1206.     }
  1207.   }
  1208.   
  1209.   ch->size() += Mac802_16pkt::getMOB_MSHO_REQ_size(req_frame);
  1210.   wimaxHdr->header.cid = peer->getPrimary()->get_cid();
  1211.   peer->getPrimary()->enqueue (p);
  1212. }
  1213. /**
  1214.  * Process a BSHO-RSP message 
  1215.  * @param frame The handover response frame
  1216.  */
  1217. void SSscheduler::process_bsho_rsp (mac802_16_mob_bsho_rsp_frame *frame)
  1218. {
  1219.   mac_->debug ("At %f in Mac %d, received handover responsen", NOW, mac_->addr());
  1220.  
  1221.   //go and switch to the channel recommended by the BS
  1222.   int targetBS = frame->n_rec[0].neighbor_bsid;
  1223.   PeerNode *peer = mac_->getPeerNode_head();      
  1224.   if (peer->getPeerNode ()==targetBS) {
  1225.     mac_->debug ("tDecision to stay in current BSn");
  1226.     return;
  1227.   }
  1228.   scan_info_->nbr = nbr_db_->getNeighbor (targetBS);
  1229.   Packet *p;
  1230.   struct hdr_cmn *ch;
  1231.   hdr_mac802_16 *wimaxHdr;
  1232.   mac802_16_mob_ho_ind_frame *ind_frame;
  1233.   
  1234.   
  1235.   p = mac_->getPacket ();
  1236.   ch = HDR_CMN(p);
  1237.   wimaxHdr = HDR_MAC802_16(p);
  1238.   p->allocdata (sizeof (struct mac802_16_mob_ho_ind_frame));
  1239.   ind_frame = (mac802_16_mob_ho_ind_frame*) p->accessdata();
  1240.   ind_frame->type = MAC_MOB_HO_IND;
  1241.   
  1242.   ind_frame->mode = 0; //HO
  1243.   ind_frame->ho_ind_type = 0; //Serving BS release
  1244.   ind_frame->rng_param_valid_ind = 0;
  1245.   ind_frame->target_bsid = targetBS;
  1246.   
  1247.   ch->size() += Mac802_16pkt::getMOB_HO_IND_size(ind_frame);
  1248.   wimaxHdr->header.cid = peer->getPrimary()->get_cid();
  1249.   peer->getPrimary()->enqueue (p);
  1250.   
  1251. #ifdef USE_802_21
  1252.   mac_->send_link_handoff_imminent (mac_->addr(), peer->getPeerNode(), targetBS);
  1253.   mac_->debug ("At %f in Mac %d link handoff imminentn", NOW, mac_->addr());
  1254.   
  1255. #endif 
  1256.   
  1257.   mac_->debug ("tHandover to BS %dn", targetBS);
  1258.   scan_info_->handoff_timeout = 20;
  1259.   scan_info_->substate = HANDOVER_PENDING;
  1260.   //mac_->setChannel (scan_info_->bs_infos[i].channel);
  1261.   //lost_synch ();
  1262.   
  1263. }
  1264. /**
  1265.  * Process a NBR_ADV message 
  1266.  * @param frame The handover response frame
  1267.  */
  1268. void SSscheduler::process_nbr_adv (mac802_16_mob_nbr_adv_frame *frame)
  1269. {
  1270.   mac_->debug ("At %f in Mac %d, received neighbor advertisementn", NOW, mac_->addr());
  1271.   mac802_16_mob_nbr_adv_frame *copy;
  1272.   copy  = (mac802_16_mob_nbr_adv_frame *) malloc (sizeof (mac802_16_mob_nbr_adv_frame));
  1273.   memcpy (copy, frame, sizeof (mac802_16_mob_nbr_adv_frame));
  1274.   //all we need is to store the information. We will process that only
  1275.   //when we will look for another station
  1276.   for (int i = 0 ; i < frame->n_neighbors ; i++) {
  1277.     int nbrid = frame->nbr_info[i].nbr_bsid;
  1278.     mac802_16_nbr_adv_info *info = (mac802_16_nbr_adv_info *) malloc (sizeof(mac802_16_nbr_adv_info));
  1279.     NeighborEntry *entry = nbr_db_->getNeighbor (nbrid);
  1280.     if (entry==NULL){
  1281.       entry = new NeighborEntry (nbrid);
  1282.       nbr_db_->addNeighbor (entry);
  1283.     }
  1284.     memcpy(info, &(frame->nbr_info[i]), sizeof(mac802_16_nbr_adv_info));
  1285.     if (entry->getNbrAdvMessage ())
  1286.       free (entry->getNbrAdvMessage());
  1287.     entry->setNbrAdvMessage(info);
  1288.     if (info->dcd_included) {
  1289.       //set DCD 
  1290.       mac802_16_dcd_frame *tmp = (mac802_16_dcd_frame *)malloc (sizeof(mac802_16_dcd_frame));
  1291.       memcpy(tmp, &(info->dcd_settings), sizeof(mac802_16_dcd_frame));
  1292.       entry->setDCD(tmp);
  1293.     }
  1294.     else 
  1295.       entry->setDCD(NULL);
  1296.     if (info->ucd_included) {
  1297.       //set DCD 
  1298.       mac802_16_ucd_frame *tmp = (mac802_16_ucd_frame *)malloc (sizeof(mac802_16_ucd_frame));
  1299.       memcpy(tmp, &(info->ucd_settings), sizeof(mac802_16_ucd_frame));
  1300.       entry->setUCD(tmp);
  1301. #ifdef DEBUG_WIMAX
  1302.       debug2 ("Dump information nbr in Mac %d for nbr %d %lxn", mac_->addr(), nbrid, (long)tmp);
  1303.       int nb_prof = tmp->nb_prof;
  1304.       mac802_16_ucd_profile *profiles = tmp->profiles;
  1305.       for (int i = 0 ; i < nb_prof ; i++) {
  1306. debug2 ("t Reading ul profile %i: f=%d, rate=%d, iuc=%dn", i, 0, profiles[i].fec, profiles[i].uiuc);
  1307.       }
  1308. #endif
  1309.     }
  1310.     else
  1311.       entry->setUCD(NULL);
  1312.   }  
  1313. }