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

网络

开发平台:

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 "bsscheduler.h"
  19. #include "burst.h"
  20. #include "dlburst.h"
  21. #include "ulburst.h"
  22. #include "random.h"
  23. #include "wimaxctrlagent.h"
  24. /**
  25.  * Bridge to TCL for BSScheduler
  26.  */
  27. static class BSSchedulerClass : public TclClass {
  28. public:
  29.   BSSchedulerClass() : TclClass("WimaxScheduler/BS") {}
  30.   TclObject* create(int, const char*const*) {
  31.     return (new BSScheduler());
  32.     
  33.   }
  34. } class_bsscheduler;
  35. /*
  36.  * Create a scheduler
  37.  */
  38. BSScheduler::BSScheduler () : cl_head_(0), cl_tail_(0), ctrlagent_(0)
  39. {
  40.   debug2 ("BSScheduler createdn");
  41.   LIST_INIT (&t17_head_);
  42.   LIST_INIT (&scan_stations_);
  43.   LIST_INIT (&fast_ranging_head_);
  44.   bw_peer_ = NULL;
  45.   bw_node_index_ = 0;
  46.   default_mod_ = OFDM_BPSK_1_2;
  47.   contention_size_ = MIN_CONTENTION_SIZE;
  48.   sendDCD = false;
  49.   dlccc_ = 0;
  50.   sendUCD = false;
  51.   ulccc_ = 0;
  52. }
  53.  
  54. /*
  55.  * Interface with the TCL script
  56.  * @param argc The number of parameter
  57.  * @param argv The list of parameters
  58.  */
  59. int BSScheduler::command(int argc, const char*const* argv)
  60. {
  61.   if (argc == 3) {
  62.     if (strcmp(argv[1], "set-default-modulation") == 0) {
  63.       if (strcmp(argv[2], "OFDM_BPSK_1_2") == 0)
  64. default_mod_ = OFDM_BPSK_1_2;
  65.       else if (strcmp(argv[2], "OFDM_QPSK_1_2") == 0)
  66. default_mod_ = OFDM_QPSK_1_2;
  67.       else if (strcmp(argv[2], "OFDM_QPSK_3_4") == 0)
  68. default_mod_ = OFDM_QPSK_3_4;
  69.       else if (strcmp(argv[2], "OFDM_16QAM_1_2") == 0)
  70. default_mod_ = OFDM_16QAM_1_2;
  71.       else if (strcmp(argv[2], "OFDM_16QAM_3_4") == 0)
  72. default_mod_ = OFDM_16QAM_3_4;
  73.       else if (strcmp(argv[2], "OFDM_64QAM_2_3") == 0)
  74. default_mod_ = OFDM_64QAM_2_3;
  75.       else if (strcmp(argv[2], "OFDM_64QAM_3_4") == 0)
  76. default_mod_ = OFDM_64QAM_3_4;
  77.       else
  78. return TCL_ERROR;
  79.       return TCL_OK;
  80.     }
  81.     else if (strcmp(argv[1], "set-contention-size") == 0) {
  82.       contention_size_ = atoi (argv[2]);
  83.       assert (contention_size_>=0);
  84.       return TCL_OK;
  85.     }
  86.   }
  87.   return TCL_ERROR;
  88. }
  89. /**
  90.  * Initializes the scheduler
  91.  */
  92. void BSScheduler::init ()
  93. {
  94.   WimaxScheduler::init();
  95.   /*print debug information */
  96.   int nbPS = (int) round((mac_->getFrameDuration()/mac_->getPhy()->getPS()));
  97.   debug2 ("duration=%f, PStime=%f, nbPS=%d,Symbol time=%f, %d n",mac_->getFrameDuration(), mac_->getPhy()->getPS(), nbPS, mac_->getPhy()->getSymbolTime (), mac_->getPhy()->getSymbolPS());
  98.   //At initialization, allocate one DL burst 
  99.   //and contention windows
  100.   //1-create one profile to be used for broadcast 
  101.   //  packets (and DL_MAP...)
  102.   Profile *p = map_->getDlSubframe()->addProfile ((int)round((mac_->getPhy()->getFreq()/1000)), default_mod_);
  103.   p->setIUC (DIUC_PROFILE_1);
  104.   map_->getDlSubframe()->getPdu ()->setPreamble (DL_PREAMBLE); //preamble + fch
  105.   //2-add the burst to carry the broadcast message
  106.   DlBurst *b = (DlBurst*) map_->getDlSubframe()->getPdu ()->addBurst (0);
  107.   b->setCid ( BROADCAST_CID );
  108.   b->setIUC (p->getIUC());
  109.   b->setStarttime (0); //after preamble and fch
  110.   b->setDuration (INIT_DL_DURATION); //enough to send DL_MAP...
  111.   b->setPreamble(true); //this is the first burst after preamble
  112.   //3-Add the End of map element
  113.   b = (DlBurst*) map_->getDlSubframe()->getPdu ()->addBurst (1);
  114.   b->setIUC (DIUC_END_OF_MAP);
  115.   b->setStarttime (INIT_DL_DURATION);
  116.   //create uplink 
  117.   //start of UL subframe is after DL and TTG and unit is PS
  118.   int starttime = (INIT_DL_DURATION+DL_PREAMBLE)*mac_->getPhy()->getSymbolPS()+mac_->phymib_.ttg;
  119.   map_->getUlSubframe()->setStarttime (starttime);
  120.   int slotleft = nbPS - starttime - mac_->phymib_.rtg;
  121.   //duration is in unit of ofdm symbols
  122.   int rangingslot = slotleft/2;
  123.   int rangingduration =(int) round(((mac_->getPhy()->getPS()*rangingslot)/mac_->getPhy()->getSymbolTime()));
  124.   int bwduration = (int) round(((mac_->getPhy()->getPS()*(slotleft - rangingslot))/mac_->getPhy()->getSymbolTime()));
  125.   //we open the uplink to initial ranging and bw requests
  126.   //add profile for the ranging burst
  127.   p = map_->getUlSubframe()->addProfile (0, default_mod_);
  128.   p->setIUC (UIUC_INITIAL_RANGING);
  129.   ContentionSlot *slot = map_->getUlSubframe()->getRanging ();
  130.   slot->setSize (getInitRangingopportunity ());
  131.   slot->setBackoff_start (mac_->macmib_.rng_backoff_start);
  132.   slot->setBackoff_stop (mac_->macmib_.rng_backoff_stop);
  133.   //create burst to represent the contention slot
  134.   Burst* b2 = map_->getUlSubframe()->addPhyPdu (0,0)->addBurst (0);
  135.   b2->setIUC (UIUC_INITIAL_RANGING);
  136.   b2->setDuration (rangingduration);
  137.   b2->setStarttime (0); //we put the contention at the begining
  138.   //now the bw request
  139.   //add profile for the bw burst
  140.   p = map_->getUlSubframe()->addProfile (0, default_mod_);
  141.   p->setIUC (UIUC_REQ_REGION_FULL);  
  142.   slot = map_->getUlSubframe()->getBw_req ();
  143.   slot->setSize (getBWopportunity ());
  144.   slot->setBackoff_start (mac_->macmib_.bw_backoff_start);
  145.   slot->setBackoff_stop (mac_->macmib_.rng_backoff_stop);
  146.   b2 = map_->getUlSubframe()->addPhyPdu (1,0)->addBurst (0);
  147.   b2->setIUC (UIUC_REQ_REGION_FULL);
  148.   b2->setDuration (bwduration);
  149.   b2->setStarttime (rangingduration); //start after the ranging slot
  150.   //end of map
  151.   b2 = map_->getUlSubframe()->addPhyPdu (2,0)->addBurst (0);
  152.   b2->setIUC (UIUC_END_OF_MAP);
  153.   b2->setStarttime (rangingduration+bwduration);
  154.   //schedule the first frame by using a random backoff to avoid
  155.   //synchronization between BSs.
  156.   double stime = Random::uniform(0, mac_->getFrameDuration ());
  157.   dl_timer_->sched (stime);
  158.   ul_timer_->sched (stime+starttime*mac_->getPhy()->getPS());
  159.   //also start the DCD and UCD timer
  160.   dcdtimer_ = new WimaxDCDTimer (mac_);
  161.   ucdtimer_ = new WimaxUCDTimer (mac_);
  162.   nbradvtimer_ = new WimaxMobNbrAdvTimer (mac_);
  163.   dcdtimer_->start (mac_->macmib_.dcd_interval);
  164.   ucdtimer_->start (mac_->macmib_.ucd_interval);
  165.   nbradvtimer_->start (mac_->macmib_.nbr_adv_interval+stime);
  166. }
  167. /**
  168.  * Compute and return the bandwidth request opportunity size
  169.  * @return The bandwidth request opportunity size
  170.  */
  171. int BSScheduler::getBWopportunity ()
  172. {
  173.   int nbPS = BW_REQ_PREAMBLE * mac_->getPhy()->getSymbolPS();
  174.   //add PS for carrying header
  175.   nbPS += (int) round((mac_->getPhy()->getTrxTime (HDR_MAC802_16_SIZE, map_->getUlSubframe()->getProfile(UIUC_REQ_REGION_FULL)->getEncoding())/mac_->getPhy()->getPS ()));
  176.   //printf ("BWopportunity size=%dn", nbPS);
  177.   return nbPS;
  178. }
  179. /**
  180.  * Compute and return the initial ranging opportunity size
  181.  * @return The initial ranging opportunity size
  182.  */
  183. int BSScheduler::getInitRangingopportunity ()
  184. {
  185.   int nbPS = INIT_RNG_PREAMBLE * mac_->getPhy()->getSymbolPS();
  186.   //add PS for carrying header
  187.   nbPS += (int) round((mac_->getPhy()->getTrxTime (RNG_REQ_SIZE+HDR_MAC802_16_SIZE, map_->getUlSubframe()->getProfile(UIUC_INITIAL_RANGING)->getEncoding())/mac_->getPhy()->getPS ()));
  188.   //printf ("Init ranging opportunity size=%dn", nbPS);
  189.   return nbPS;  
  190. }
  191. /**
  192.  * Called when a timer expires
  193.  * @param The timer ID
  194.  */
  195. void BSScheduler::expire (timer_id id)
  196. {
  197.   switch (id) {
  198.   case WimaxDCDTimerID:
  199.     sendDCD = true;
  200.     mac_->debug ("At %f in Mac %d DCDtimer expiredn", NOW, mac_->addr());
  201.     dcdtimer_->start (mac_->macmib_.dcd_interval);
  202.     break;
  203.   case WimaxUCDTimerID:
  204.     sendUCD = true;
  205.     mac_->debug ("At %f in Mac %d UCDtimer expiredn", NOW, mac_->addr());
  206.     ucdtimer_->start (mac_->macmib_.ucd_interval);
  207.     break;
  208.   case WimaxMobNbrAdvTimerID:
  209.     send_nbr_adv();
  210.     nbradvtimer_->start (mac_->macmib_.nbr_adv_interval);
  211.     break;
  212.   default:
  213.     mac_->debug ("Warning: unknown timer expired in BSSchedulern");
  214.   }
  215. }
  216. /**
  217.  * Set the control agent
  218.  */
  219. void BSScheduler::setCtrlAgent (WimaxCtrlAgent *agent)
  220. {
  221.   assert (agent);
  222.   ctrlagent_ = agent;
  223. }
  224. /**
  225.  * Process a packet received by the Mac. Only scheduling related packets should be sent here (BW request, UL_MAP...)
  226.  * @param p The packet to process
  227.  */
  228. void BSScheduler::process (Packet * p)
  229. {
  230.   //assert (mac_);
  231.   //debug2 ("BSScheduler received packet to processn");
  232.   assert (mac_ && HDR_CMN(p)->ptype()==PT_MAC);
  233.   debug2 ("BSScheduler received packet to processn");
  234.   
  235.   hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(p);
  236.   gen_mac_header_t header = wimaxHdr->header;
  237.   //check if this is a bandwidth request
  238.   if (header.ht == 1) {
  239.     process_bw_req (p);
  240.     return;
  241.   }
  242.   //we cast to this frame because all management frame start with
  243.   //a type 
  244.   mac802_16_dl_map_frame *frame = (mac802_16_dl_map_frame*) p->accessdata();
  245.   
  246.   switch (frame->type) {
  247.   case MAC_RNG_REQ: 
  248.     process_ranging_req (p);
  249.     break;
  250.   case MAC_REG_REQ: 
  251.     process_reg_req (p);
  252.     break;
  253.   case MAC_MOB_SCN_REQ:
  254.     if (ctrlagent_) 
  255.       ctrlagent_->process_scan_request (p);
  256.     else
  257.       fprintf (stderr, "Warning: no controler to handle scan request in BS %dn", mac_->addr());
  258.     break;
  259.   case MAC_MOB_MSHO_REQ:
  260.     process_msho_req (p);
  261.     break;
  262.   case MAC_MOB_HO_IND:
  263.     process_ho_ind (p);
  264.     break;
  265.   default:
  266.     mac_->debug ("unknown packet in BSn");
  267.   }
  268.   Packet::free (p);
  269. }
  270. /**
  271.  * Return the type of STA this scheduler is good for
  272.  * @return STA_BS
  273.  */
  274. station_type_t BSScheduler::getNodeType ()
  275. {
  276.   return STA_BS;
  277. }
  278. /**
  279.  * Start a new frame
  280.  */
  281. void BSScheduler::start_ulsubframe ()
  282. {
  283.   //mac_->debug ("At %f in Mac %d BS scheduler ulsubframe expiresn", NOW, mac_->addr());
  284.   //change PHY state
  285.   mac_->getPhy()->setMode (OFDM_RECV);  
  286.   //start handler of ulsubframe
  287.   map_->getUlSubframe()->getTimer()->sched (0);
  288.   //reschedule for next frame
  289.   ul_timer_->resched (mac_->getFrameDuration());
  290. }
  291. /**
  292.  * Start a new frame
  293.  */
  294. void BSScheduler::start_dlsubframe ()
  295. {
  296.   debug2 ("At %f in Mac %d BS scheduler dlsubframe expires (frame=%d)n", 
  297.        NOW, mac_->addr(), mac_->frame_number_+1);
  298.   assert (map_);
  299.   Packet *p;
  300.   Burst *b;
  301.   struct hdr_cmn *ch;
  302.   double txtime;
  303.   int txtime_s;
  304.   OFDMPhy *phy = mac_->getPhy();
  305.   //increment frame number
  306.   mac_->frame_number_ ++;
  307.   
  308.   //adjust frame start information
  309.   map_->setStarttime(NOW);
  310.   /* First lets clear the peers we haven't heard of for long time */
  311.   for (PeerNode *pn = mac_->getPeerNode_head() ; pn ; ) {
  312.     PeerNode *tmp = pn->next_entry(); //next elem
  313.     if (isPeerScanning(pn->getPeerNode())) {
  314.       //since a scanning node cannot send data we push the 
  315.       //timeout while it is scanning
  316.       pn->setRxTime(NOW); 
  317.     } else if (NOW-pn->getRxTime()>mac_->macmib_.client_timeout) {
  318.       mac_->debug ("Client timeout for node %dn", pn->getPeerNode());
  319.       mac_->removePeerNode(pn);
  320.     }
  321.     pn = tmp;
  322.   }
  323.   /**** Step one : burst allocation ****/
  324.   int nbPS = (int) round((mac_->getFrameDuration()/phy->getPS()));
  325.   int nbPS_left = nbPS - mac_->phymib_.rtg - mac_->phymib_.ttg;
  326.   int nbSymbols = (int) ((phy->getPS()*nbPS_left)/phy->getSymbolTime());
  327.   int dlduration = INIT_DL_DURATION+DL_PREAMBLE;
  328.   int ulduration = 0;
  329.   debug2 ("Frame: duration=%f, PSduration=%e, symboltime=%e, nbPS=%d, rtg=%d, ttg=%d, PSleft=%d, nbSymbols=%d, ", 
  330.     mac_->getFrameDuration(), phy->getPS(), phy->getSymbolTime(), nbPS, mac_->phymib_.rtg, mac_->phymib_.ttg, nbPS_left, nbSymbols);
  331.   //remove control messages
  332.   nbSymbols -= INIT_DL_DURATION+DL_PREAMBLE;
  333.   
  334.   nbSymbols -=10;
  335.   for (Connection *c = mac_->getCManager()->get_down_connection (); c && nbSymbols>0 ; c=c->next_entry()) {
  336.     if (c->getPeerNode() && !isPeerScanning (c->getPeerNode()->getPeerNode())) {
  337.       int queuesize = c->queueByteLength();
  338.       int tmp = (int) round((phy->getTrxTime (queuesize, map_->getDlSubframe()->getProfile (DIUC_PROFILE_1)->getEncoding())/phy->getSymbolTime()));
  339.       if (tmp < nbSymbols) {
  340. dlduration += tmp;
  341. nbSymbols -= tmp;
  342.       }else{
  343. dlduration +=nbSymbols;
  344. nbSymbols -= nbSymbols;
  345. break;
  346.       }
  347.     }
  348.   }
  349.   nbSymbols +=10;
  350.   map_->getDlSubframe()->getPdu()->getBurst(0)->setDuration (dlduration);
  351.   map_->getUlSubframe()->setStarttime (dlduration*phy->getSymbolPS()+mac_->phymib_.rtg);
  352.   ul_timer_->resched (map_->getUlSubframe()->getStarttime()*mac_->getPhy()->getPS());
  353.   debug2 ("dlduration=%d, ", dlduration);
  354.   //update the END_OF_MAP start time
  355.   b = (DlBurst*) map_->getDlSubframe()->getPdu ()->getBurst (1);
  356.   b->setStarttime (dlduration);  
  357.   while (map_->getUlSubframe()->getNbPdu()>0) {
  358.     PhyPdu *pdu = map_->getUlSubframe()->getPhyPdu(0);
  359.     map_->getUlSubframe()->removePhyPdu(pdu);
  360.     delete (pdu);
  361.   }
  362.   
  363.   int rangingduration = 0;
  364.   int bwduration = 0;
  365.   int pduIndex = 0;
  366.   debug2 ("In Mac %d Nb symbols left before contention =%dn", mac_->addr(), nbSymbols);
  367.   int contentionslots = (int) round((contention_size_*((getBWopportunity()+getInitRangingopportunity())*mac_->getPhy()->getPS()/mac_->getPhy()->getSymbolTime())));
  368.   if (nbSymbols > contentionslots) {
  369.     int starttime, slotleft, rangingslot, bwslot;
  370.     //create uplink 
  371.     //start of UL subframe is after DL and TTG and unit is PS
  372.     starttime = map_->getUlSubframe()->getStarttime();
  373.     slotleft = nbPS - starttime - mac_->phymib_.rtg;
  374.     //if there is at least one peer, then use only contention_size_ symbols, 
  375.     //otherwise use all the bw
  376.     if (mac_->getPeerNode_head() || fast_ranging_head_.lh_first) {
  377.       rangingslot = contention_size_*getInitRangingopportunity();
  378.       bwslot = contention_size_*getBWopportunity();
  379.       nbSymbols -= contentionslots;
  380.       debug2 ("nbSymbols after contention=%dn", nbSymbols);
  381.     }
  382.     else {
  383.       rangingslot = (int) (floor (slotleft/(2.0*getInitRangingopportunity()))*getInitRangingopportunity());
  384.       bwslot = (int) (floor ((slotleft-rangingslot)/getBWopportunity())*getBWopportunity());
  385.       nbSymbols = 0;
  386.     }    
  387.     rangingduration =(int) round(((mac_->getPhy()->getPS()*rangingslot)/mac_->getPhy()->getSymbolTime()));
  388.     bwduration = (int) round (((mac_->getPhy()->getPS()*bwslot)/mac_->getPhy()->getSymbolTime()));
  389.     //we open the uplink to initial ranging and bw requests
  390.     ContentionSlot *slot = map_->getUlSubframe()->getRanging ();
  391.     //create burst to represent the contention slot
  392.     Burst* b2 = map_->getUlSubframe()->addPhyPdu (pduIndex,0)->addBurst (0);
  393.     pduIndex++;
  394.     b2->setIUC (UIUC_INITIAL_RANGING);
  395.     b2->setDuration (rangingduration);
  396.     b2->setStarttime (ulduration); //we put the contention at the begining
  397.     ulduration += rangingduration;
  398.     
  399.     //now the bw request
  400.     slot = map_->getUlSubframe()->getBw_req ();
  401.     b2 = map_->getUlSubframe()->addPhyPdu (pduIndex,0)->addBurst (0);
  402.     pduIndex++;
  403.     b2->setIUC (UIUC_REQ_REGION_FULL);
  404.     b2->setDuration (bwduration);
  405.     b2->setStarttime (ulduration); //start after the ranging slot
  406.     ulduration += bwduration;
  407.   }
  408.   
  409.   //check if there is Fast Ranging allocation to do
  410.   while (fast_ranging_head_.lh_first !=NULL 
  411.  && fast_ranging_head_.lh_first->frame() == mac_->getFrameNumber()) {
  412.     //we need to include a fast ranging allocation
  413.     b = map_->getUlSubframe()->addPhyPdu (pduIndex,0)->addBurst (0);
  414.     pduIndex++;
  415.     int tmp =(int) round(((mac_->getPhy()->getPS()*getInitRangingopportunity())/mac_->getPhy()->getSymbolTime()));    
  416.     b->setIUC (UIUC_EXT_UIUC);
  417.     b->setDuration (tmp);
  418.     b->setStarttime (ulduration); //start after previous slot
  419.     ((UlBurst*)b)->setFastRangingParam (fast_ranging_head_.lh_first->macAddr(), UIUC_INITIAL_RANGING);
  420.     ulduration += tmp;
  421.     mac_->debug ("At %f in Mac %d adding fast ranging for %dn", NOW, mac_->addr(), fast_ranging_head_.lh_first->macAddr());
  422.     fast_ranging_head_.lh_first->remove_entry();
  423.   }
  424.   //get the next node to allocate bw. 
  425.   //PB: the node may have been removed. We need to check that
  426.   PeerNode *peer = mac_->getPeerNode_head();
  427.   PeerNode *start_peer = mac_->getPeerNode_head(); 
  428.   int i=0;
  429.   if (start_peer != NULL) {
  430.     //we have at least one element in the list
  431.     for (peer = mac_->getPeerNode_head(); peer->next_entry() ; peer=peer->next_entry());
  432.     debug2 ("start_peer=%d, peer=%dn", start_peer->getPeerNode(), peer->getPeerNode());
  433.     while (start_peer != peer) {
  434.       if (!isPeerScanning(peer->getPeerNode())) {
  435. debug2 ("peer %d not scanning take itn", peer->getPeerNode());
  436. break; //we found next station
  437.       }
  438.       debug2 ("peer %d scanning move itn", peer->getPeerNode());
  439.       peer->remove_entry();
  440.       mac_->addPeerNode (peer); //we put it at head of the list
  441.       for (peer = mac_->getPeerNode_head(); peer->next_entry() ; peer=peer->next_entry());
  442.     }
  443.   }
  444.   if (peer)
  445.     debug2 ("final pick is %dn", peer->getPeerNode());
  446.   //update variables
  447.   bw_node_index_ = i;
  448.   bw_peer_ = peer;
  449.   
  450.   //the next peer node takes the rest of the bw
  451.   if (nbSymbols > 0 && peer && !isPeerScanning(peer->getPeerNode())) {
  452.     debug2 ("Allocate uplink for STA %dn", peer->getPeerNode());
  453.     peer->remove_entry();
  454.     mac_->addPeerNode (peer); //we put it at head of the list
  455.     //printf ("NbSymbols for node=%dn", nbSymbols);
  456.     //add burst
  457.     Burst *b3 = map_->getUlSubframe()->addPhyPdu (pduIndex,0)->addBurst (0);
  458.     pduIndex++;
  459.     b3->setIUC (UIUC_PROFILE_1);
  460.     b3->setCid (peer->getPrimary()->get_cid());
  461.     b3->setDuration (nbSymbols);
  462.     b3->setStarttime (ulduration); 
  463.     //add profile if not existing
  464.     Profile *p = map_->getUlSubframe()->getProfile (UIUC_PROFILE_1);
  465.     if (p==NULL) {
  466.       p = map_->getUlSubframe()->addProfile (0, default_mod_);
  467.       p->setIUC (UIUC_PROFILE_1);
  468.     }
  469.   }
  470.   
  471.   //end of map
  472.   Burst *b2 = map_->getUlSubframe()->addPhyPdu (pduIndex,0)->addBurst (0);
  473.   pduIndex++;
  474.   b2->setIUC (UIUC_END_OF_MAP);
  475.   b2->setStarttime (rangingduration+bwduration+nbSymbols);
  476.   
  477.   //we need to fill up the outgoing queues
  478.   for (int index = 0 ; index < map_->getDlSubframe()->getPdu ()->getNbBurst() ; index++) {
  479.     b = map_->getDlSubframe()->getPdu ()->getBurst (index);
  480.     int duration = 0; 
  481.     if (b->getIUC()==DIUC_END_OF_MAP) {
  482.       //consistency check..
  483.       assert (index == map_->getDlSubframe()->getPdu ()->getNbBurst()-1);
  484.       break;
  485.     }
  486.     
  487.     //we can get the next one after we check END_OF_MAP
  488.     //b2 = map_->getDlSubframe()->getPdu ()->getBurst (index+1);
  489.     //if this is the first buffer, add DL_MAP...messages
  490.     if (index==0) {
  491.       p = map_->getDL_MAP();
  492.       ch = HDR_CMN(p);
  493.       txtime = phy->getTrxTime (ch->size(), map_->getDlSubframe()->getProfile (b->getIUC())->getEncoding());
  494.       ch->txtime() = txtime;
  495.       txtime_s = (int) round(txtime/phy->getSymbolTime ()); //in units of symbol 
  496.       assert ((duration+txtime_s) <= b->getDuration());
  497.       b->enqueue(p);      //enqueue into burst
  498.       duration += txtime_s;
  499.       p = map_->getUL_MAP();
  500.       ch = HDR_CMN(p);
  501.       txtime = phy->getTrxTime (ch->size(), map_->getDlSubframe()->getProfile (b->getIUC())->getEncoding());
  502.       ch->txtime() = txtime;
  503.       txtime_s = (int) round(txtime/phy->getSymbolTime ()); //in units of symbol 
  504.       assert ((duration+txtime_s) <= b->getDuration());
  505.       b->enqueue(p);      //enqueue into burst
  506.       duration += txtime_s;
  507.       if (sendDCD || map_->getDlSubframe()->getCCC()!= dlccc_) {
  508. p = map_->getDCD();
  509. ch = HDR_CMN(p);
  510. txtime = phy->getTrxTime (ch->size(), map_->getDlSubframe()->getProfile (b->getIUC())->getEncoding());
  511. ch->txtime() = txtime;
  512. txtime_s = (int) round(txtime/phy->getSymbolTime ()); //in units of symbol 
  513. assert ((duration+txtime_s) <= b->getDuration());
  514. b->enqueue(p);      //enqueue into burst
  515. duration += txtime_s;
  516. sendDCD = false;
  517. dlccc_ = map_->getDlSubframe()->getCCC();
  518. //reschedule timer
  519. dcdtimer_->stop();
  520. dcdtimer_->start (mac_->macmib_.dcd_interval);
  521.       }
  522.       
  523.       if (sendUCD || map_->getUlSubframe()->getCCC()!= ulccc_) {
  524. p = map_->getUCD();
  525. ch = HDR_CMN(p);
  526. txtime = phy->getTrxTime (ch->size(), map_->getDlSubframe()->getProfile (b->getIUC())->getEncoding());
  527. ch->txtime() = txtime;
  528. txtime_s = (int) round(txtime/phy->getSymbolTime ()); //in units of symbol 
  529. assert ((duration+txtime_s) <= b->getDuration());
  530. b->enqueue(p);      //enqueue into burst
  531. duration += txtime_s;
  532. sendUCD = false;
  533. ulccc_ = map_->getUlSubframe()->getCCC();
  534. //reschedule timer
  535. ucdtimer_->stop();
  536. ucdtimer_->start (mac_->macmib_.ucd_interval);
  537.       }
  538.     }
  539.       
  540.     //get the packets from the connection with the same CID
  541.     //Connection *c=mac_->getCManager ()->get_connection (b->getCid());
  542.     int nb_down = 0;
  543.     for (Connection *c = mac_->getCManager()->get_down_connection (); c ; c=c->next_entry()){ nb_down++;}
  544.     Connection **tmp_con = (Connection **) malloc (nb_down*sizeof (Connection *));
  545.     int i=0;
  546.     for (Connection *c = mac_->getCManager()->get_down_connection (); c ; c=c->next_entry()){
  547.       tmp_con[i] = c;
  548.       i++;
  549.     }
  550.     //we randomly pick the connection we'll start serving first
  551.     int start_index = (int) round (Random::uniform(0, nb_down));
  552.     debug2 ("Picked connection %d as firstn", start_index);
  553.     //for (Connection *c = mac_->getCManager()->get_down_connection (); c ; c=c->next_entry()) {
  554.     for (i=0; i < nb_down ; i++) {
  555.       int index = (i+start_index)%nb_down;
  556.       Connection *c=tmp_con[index];
  557.       if (c->getPeerNode() && isPeerScanning (c->getPeerNode()->getPeerNode()))
  558. continue;
  559.       duration = transfer_packets (c, b, duration);
  560.     }
  561.   }
  562.   //change PHY state
  563.   mac_->getPhy()->setMode (OFDM_SEND);
  564.   //start handler of dlsubframe
  565.   map_->getDlSubframe()->getTimer()->sched (0);
  566.   //reschedule for next time (frame duration)
  567.   dl_timer_->resched (mac_->getFrameDuration());  
  568. }
  569. /** Add a new Fast Ranging allocation
  570.  * @param time The time when to allocate data
  571.  * @param macAddr The MN address
  572.  */
  573. void BSScheduler::addNewFastRanging (double time, int macAddr)
  574. {
  575.   //compute the frame where the allocation will be located
  576.   int frame = int ((time-NOW)/mac_->getFrameDuration()) +2 ;
  577.   frame += mac_->getFrameNumber();
  578.   //printf ("Added fast RA for frame %d (current=%d) for time (%f)n", 
  579.   //   frame, mac_->getFrameNumber(), time);
  580.   FastRangingInfo *info= new FastRangingInfo (frame, macAddr);
  581.   info->insert_entry(&fast_ranging_head_);
  582. }
  583. /**** Packet processing methods ****/
  584. /**
  585.  * Process a RNG-REQ message
  586.  * @param p The packet containing the ranging request information
  587.  */
  588. void BSScheduler::process_ranging_req (Packet *p)
  589. {
  590.   UlSubFrame *ulsubframe = map_->getUlSubframe();
  591.   mac802_16_rng_req_frame *req = (mac802_16_rng_req_frame *) p->accessdata();
  592.   if (HDR_MAC802_16(p)->header.cid != INITIAL_RANGING_CID) {
  593.     //process request for DIUC
  594.   } else {
  595.     //here we can make decision to accept the SS or not.
  596.     //for now, accept everybody
  597.     //check if CID already assigned for the SS
  598.     PeerNode *peer = mac_->getPeerNode (req->ss_mac_address);
  599.     if (peer==NULL) {
  600.       mac_->debug ("New peer node requesting ranging (%d)n",req->ss_mac_address);
  601.       //Assign Management CIDs
  602.       Connection *basic = new Connection (CONN_BASIC);
  603.       Connection *upbasic = new Connection (CONN_BASIC, basic->get_cid());
  604.       Connection *primary = new Connection (CONN_PRIMARY);
  605.       Connection *upprimary = new Connection (CONN_PRIMARY, primary->get_cid());
  606.       
  607.       //Create Peer information
  608.       peer = new PeerNode (req->ss_mac_address);
  609.       peer->setBasic (basic);
  610.       peer->setPrimary (primary);
  611.       upbasic->setPeerNode (peer);
  612.       upprimary->setPeerNode (peer);
  613.       mac_->addPeerNode (peer);
  614.       mac_->getCManager()->add_connection (upbasic, true);
  615.       mac_->getCManager()->add_connection (basic, false);
  616.       mac_->getCManager()->add_connection (upprimary, true);
  617.       mac_->getCManager()->add_connection (primary, false);
  618.       //schedule timer in case the node never register
  619.       addtimer17 (req->ss_mac_address);
  620.       //create packet for answers
  621.       Packet *rep = mac_->getPacket ();
  622.       struct hdr_cmn *ch = HDR_CMN(rep);
  623.       rep->allocdata (sizeof (struct mac802_16_rng_rsp_frame));
  624.       mac802_16_rng_rsp_frame *frame = (mac802_16_rng_rsp_frame*) rep->accessdata();
  625.       frame->type = MAC_RNG_RSP;
  626.       frame->uc_id = ulsubframe->getChannelID();
  627.       frame->rng_status = RNG_SUCCESS;
  628.       frame->ss_mac_address = req->ss_mac_address;
  629.       frame->basic_cid = basic->get_cid();
  630.       frame->primary_cid = primary->get_cid();
  631.       ch->size() = RNG_RSP_SIZE;
  632.       //compute transmission time
  633.       Burst *b = map_->getDlSubframe()->getPdu ()->getBurst (0);
  634.       double txtime = mac_->getPhy()->getTrxTime (ch->size(), map_->getDlSubframe()->getProfile (b->getIUC())->getEncoding());
  635.       ch->txtime() = txtime;
  636.       //enqueue packet
  637.       mac_->getCManager()->get_connection (BROADCAST_CID, false)->enqueue (rep);
  638.       if (cl_head_==NULL) {
  639. cl_head_ = (new_client_t*)malloc (sizeof (new_client_t));
  640. cl_tail_ = cl_head_;
  641.       } else {
  642. cl_tail_->next = (new_client_t*)malloc (sizeof (new_client_t));
  643. cl_tail_=cl_tail_->next;
  644.       }
  645.       cl_tail_->cid = primary->get_cid();
  646.       cl_tail_->next = NULL;
  647. #ifdef USE_802_21
  648.       mac_->send_link_detected (mac_->addr(), peer->getPeerNode(), 1);
  649. #endif
  650.     } else {
  651.       mac_->debug ("Received ranging for known station (%d)n", req->ss_mac_address);
  652.       //reset invited ranging retries for SS
  653.       //create packet for answers
  654.       Connection *basic = peer->getBasic();
  655.       Connection *primary = peer->getPrimary();
  656.       Packet *rep = mac_->getPacket ();
  657.       struct hdr_cmn *ch = HDR_CMN(rep);
  658.       rep->allocdata (sizeof (struct mac802_16_rng_rsp_frame));
  659.       mac802_16_rng_rsp_frame *frame = (mac802_16_rng_rsp_frame*) rep->accessdata();
  660.       frame->type = MAC_RNG_RSP;
  661.       frame->uc_id = ulsubframe->getChannelID();
  662.       frame->rng_status = RNG_SUCCESS;
  663.       frame->ss_mac_address = req->ss_mac_address;
  664.       frame->basic_cid = basic->get_cid();
  665.       frame->primary_cid = primary->get_cid();
  666.       ch->size() = RNG_RSP_SIZE;
  667.       //compute transmission time
  668.       Burst *b = map_->getDlSubframe()->getPdu ()->getBurst (0);
  669.       double txtime = mac_->getPhy()->getTrxTime (ch->size(), map_->getDlSubframe()->getProfile (b->getIUC())->getEncoding());
  670.       ch->txtime() = txtime;
  671.       //enqueue packet
  672.       mac_->getCManager()->get_connection (BROADCAST_CID, false)->enqueue (rep);
  673.     }
  674.   }
  675. }
  676. /**
  677.  * Add a new timer17 in the list. It also performs cleaning of the list
  678.  * @param index The client address
  679.  */
  680. void BSScheduler::addtimer17 (int index)
  681. {
  682.   //clean expired timers
  683.   T17Element *entry;
  684.   for (entry = t17_head_.lh_first; entry ; ) {
  685.     if (entry->paused ()) {
  686.       T17Element *tmp = entry;
  687.       entry = entry->next_entry();
  688.       tmp->remove_entry();
  689.       free (tmp);
  690.     }
  691.     entry = entry->next_entry();
  692.   }
  693.   entry = new T17Element (mac_, index);
  694.   entry->insert_entry (&t17_head_);
  695. }
  696. /**
  697.  * Cancel and remove the timer17 associated with the node
  698.  * @param index The client address
  699.  */
  700. void BSScheduler::removetimer17 (int index)
  701. {
  702.   //clean expired timers
  703.   T17Element *entry;
  704.   for (entry = t17_head_.lh_first; entry ; entry = entry->next_entry()) {
  705.     if (entry->index ()==index) {
  706.       entry->cancel();
  707.       entry->remove_entry();
  708.       delete (entry);
  709.       break;
  710.     }
  711.   }
  712. }
  713. /**
  714.  * Process bandwidth request
  715.  * @param p The request
  716.  */
  717. void BSScheduler::process_bw_req (Packet *p)
  718.   hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(p);
  719.   gen_mac_header_t header = wimaxHdr->header;
  720.   bw_req_header_t *req;
  721.   req = (bw_req_header_t *)&header;
  722.   mac_->debug ("received bandwidth request of %d bytes from %dn", req->br, req->cid); 
  723.   
  724. }
  725. /**
  726.  * Process registration request
  727.  * @param p The request
  728.  */
  729. void BSScheduler::process_reg_req (Packet *req)
  730.   hdr_mac802_16 *wimaxHdr_req = HDR_MAC802_16(req);
  731.   gen_mac_header_t header_req = wimaxHdr_req->header;
  732.   
  733.   mac_->debug ("received registration request from %dn", header_req.cid);
  734.   Packet *p;
  735.   struct hdr_cmn *ch;
  736.   hdr_mac802_16 *wimaxHdr;
  737.   mac802_16_reg_rsp_frame *reg_frame;
  738.   PeerNode *peer;
  739.   //create packet for request
  740.   p = mac_->getPacket ();
  741.   ch = HDR_CMN(p);
  742.   wimaxHdr = HDR_MAC802_16(p);
  743.   p->allocdata (sizeof (struct mac802_16_reg_rsp_frame));
  744.   reg_frame = (mac802_16_reg_rsp_frame*) p->accessdata();
  745.   reg_frame->type = MAC_REG_RSP;
  746.   reg_frame->response = 0; //OK
  747.   peer = mac_->getCManager()->get_connection (header_req.cid, false)->getPeerNode();
  748.   Connection *secondary = peer->getSecondary ();
  749.   if (secondary==NULL) {
  750.     //first time 
  751.     secondary = new Connection (CONN_SECONDARY);
  752.     Connection *upsecondary = new Connection (CONN_SECONDARY, secondary->get_cid());
  753.     mac_->getCManager()->add_connection (upsecondary, true);
  754.     mac_->getCManager()->add_connection (secondary, false);
  755.     peer->setSecondary (secondary);
  756.     upsecondary->setPeerNode (peer);
  757.   }
  758.   reg_frame->sec_mngmt_cid = secondary->get_cid();
  759.   wimaxHdr->header.cid = header_req.cid;
  760.   ch->size() = REG_RSP_SIZE;
  761.   
  762.   //compute transmission time
  763.   Burst *b = map_->getDlSubframe()->getPdu ()->getBurst (0);
  764.   double txtime = mac_->getPhy()->getTrxTime (ch->size(), map_->getDlSubframe()->getProfile (b->getIUC())->getEncoding());
  765.   ch->txtime() = txtime;
  766.   //enqueue packet
  767.   mac_->getCManager()->get_connection (BROADCAST_CID, false)->enqueue (p);
  768.   //clear t17 timer for this node
  769.   removetimer17 (peer->getPeerNode());
  770. #ifdef USE_802_21
  771.   mac_->debug ("At %f in Mac %d, send link upn", NOW, mac_->addr());
  772.   mac_->send_link_up (peer->getPeerNode(),mac_->addr());
  773. #endif
  774. }
  775. /**
  776.  * Send a neighbor advertisement message
  777.  */
  778. void BSScheduler::send_nbr_adv ()
  779. {
  780.   mac_->debug ("At %f in BS %d send_nbr_adv (nb_neighbor=%d)n", NOW, mac_->addr(), nbr_db_->getNbNeighbor());
  781.   Packet *p;
  782.   struct hdr_cmn *ch;
  783.   hdr_mac802_16 *wimaxHdr;
  784.   mac802_16_mob_nbr_adv_frame *frame;
  785.   //PeerNode *peer;
  786.   //create packet for request
  787.   p = mac_->getPacket ();
  788.   ch = HDR_CMN(p);
  789.   wimaxHdr = HDR_MAC802_16(p);
  790.   p->allocdata (sizeof (struct mac802_16_mob_nbr_adv_frame));
  791.   frame = (mac802_16_mob_nbr_adv_frame*) p->accessdata();
  792.   frame->type = MAC_MOB_NBR_ADV;
  793.   frame->n_neighbors = nbr_db_->getNbNeighbor();
  794.   frame->skip_opt_field = 0;
  795.   for (int i = 0 ; i < frame->n_neighbors ; i++) {
  796.     frame->nbr_info[i].phy_profile_id.FAindex = 0;
  797.     frame->nbr_info[i].phy_profile_id.bs_eirp = 0;
  798.     frame->nbr_info[i].nbr_bsid= nbr_db_->getNeighbors()[i]->getID();
  799.     frame->nbr_info[i].dcd_included = true;
  800.     memcpy (&(frame->nbr_info[i].dcd_settings), nbr_db_->getNeighbors ()[i]->getDCD(), sizeof(mac802_16_dcd_frame));
  801.     frame->nbr_info[i].ucd_included = true;
  802.     memcpy (&(frame->nbr_info[i].ucd_settings), nbr_db_->getNeighbors ()[i]->getUCD(), sizeof(mac802_16_ucd_frame));
  803.     frame->nbr_info[i].phy_included = false;
  804.   }
  805.   ch->size() = Mac802_16pkt::getMOB_NBR_ADV_size(frame);
  806.   mac_->getCManager()->get_connection (BROADCAST_CID, false)->enqueue (p);
  807.   
  808. }
  809. /** 
  810.  * Finds out if the given station is currently scanning
  811.  * @param nodeid The MS id
  812.  */
  813. bool BSScheduler::isPeerScanning (int nodeid)
  814. {
  815.   ScanningStation *sta;
  816.   for (sta = scan_stations_.lh_first; sta ; sta = sta->next_entry()) {
  817.     if (sta->getNodeId()==nodeid && sta->isScanning(mac_->frame_number_)) {
  818.       //printf ("station %d scanningn", nodeid);
  819.       return true;
  820.     }
  821.   }
  822.   return false;
  823. }
  824. /**
  825.  * Process handover request
  826.  * @param p The request
  827.  */
  828. void BSScheduler::process_msho_req (Packet *req)
  829. {
  830.   hdr_mac802_16 *wimaxHdr_req = HDR_MAC802_16(req);
  831.   gen_mac_header_t header_req = wimaxHdr_req->header;
  832.   mac802_16_mob_msho_req_frame *req_frame = 
  833.     (mac802_16_mob_msho_req_frame*) req->accessdata();
  834.   
  835.   mac_->debug ("At %f in Mac %d received handover request from %dn", NOW, mac_->addr(), header_req.cid);
  836.   //check the BS that has stronger power
  837.   int maxIndex = 0;
  838.   int maxRssi = 0; //max value
  839.   for (int i = 0; i < req_frame->n_new_bs_full ; i++) {
  840.     if (req_frame->bs_full[i].bs_rssi_mean >= maxRssi) {
  841.       maxIndex = i;
  842.       maxRssi = req_frame->bs_full[i].bs_rssi_mean;
  843.     }
  844.   }
  845.   //reply with one recommended BS
  846.   Packet *p;
  847.   struct hdr_cmn *ch;
  848.   hdr_mac802_16 *wimaxHdr;
  849.   mac802_16_mob_bsho_rsp_frame *rsp_frame;
  850.   send_nbr_adv (); //to force update with latest information
  851.   //create packet for request
  852.   p = mac_->getPacket ();
  853.   ch = HDR_CMN(p);
  854.   wimaxHdr = HDR_MAC802_16(p);
  855.   p->allocdata (sizeof (struct mac802_16_mob_bsho_rsp_frame)+sizeof (mac802_16_mob_bsho_rsp_rec));
  856.   rsp_frame = (mac802_16_mob_bsho_rsp_frame*) p->accessdata();
  857.   rsp_frame->type = MAC_MOB_BSHO_RSP;
  858.   
  859.   rsp_frame->mode = 0; //HO request
  860.   rsp_frame->ho_operation_mode = 1; //mandatory handover response
  861.   rsp_frame->n_recommended = 1;
  862.   rsp_frame->resource_retain_flag = 0; //release connection information
  863.   rsp_frame->n_rec[0].neighbor_bsid = req_frame->bs_full[maxIndex].neighbor_bs_index;
  864.   rsp_frame->n_rec[0].ho_process_optimization=0; //no optimization
  865.   ch->size() += Mac802_16pkt::getMOB_BSHO_RSP_size(rsp_frame);
  866.   wimaxHdr->header.cid = header_req.cid;
  867.   mac_->getCManager()->get_connection (BROADCAST_CID, false)->enqueue (p);
  868. }
  869.  
  870. /**
  871.  * Process handover indication
  872.  * @param p The indication
  873.  */
  874. void BSScheduler::process_ho_ind (Packet *p)
  875. {
  876.   hdr_mac802_16 *wimaxHdr_req = HDR_MAC802_16(p);
  877.   gen_mac_header_t header_req = wimaxHdr_req->header;
  878.   //mac802_16_mob_ho_ind_frame *req_frame = 
  879.   //  (mac802_16_mob_ho_ind_frame*) p->accessdata();
  880.   
  881.   mac_->debug ("At %f in Mac %d received handover indication from %dn", NOW, mac_->addr(), header_req.cid);
  882.   
  883. }
  884.  
  885. /**
  886.  * Send a scan response to the MN
  887.  * @param rsp The response from the control
  888.  */
  889. void BSScheduler::send_scan_response (mac802_16_mob_scn_rsp_frame *rsp, int cid)
  890. {
  891.   //create packet for request
  892.   Packet *p = mac_->getPacket ();
  893.   struct hdr_cmn *ch = HDR_CMN(p);
  894.   hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(p);
  895.   p->allocdata (sizeof (struct mac802_16_mob_scn_rsp_frame));
  896.   mac802_16_mob_scn_rsp_frame* rsp_frame = (mac802_16_mob_scn_rsp_frame*) p->accessdata();
  897.   memcpy (rsp_frame, rsp, sizeof (mac802_16_mob_scn_rsp_frame));
  898.   rsp_frame->type = MAC_MOB_SCN_RSP;
  899.   
  900.   wimaxHdr->header.cid = cid;
  901.   ch->size() += Mac802_16pkt::getMOB_SCN_RSP_size(rsp_frame);
  902.   
  903.   //add scanning station to the list
  904.   PeerNode *peer = mac_->getCManager()->get_connection (cid, false)->getPeerNode();
  905.   /* The request is received in frame i, the reply is sent in frame i+1
  906.    * so the frame at which the scanning start is start_frame+2
  907.    */
  908.   ScanningStation *sta = new ScanningStation (peer->getPeerNode(), rsp_frame->scan_duration & 0xFF, 
  909.      rsp_frame->start_frame+mac_->frame_number_+2, 
  910.      rsp_frame->interleaving_interval & 0xFF,
  911.      rsp_frame->scan_iteration & 0xFF);
  912.   sta->insert_entry_head (&scan_stations_);
  913.   //compute transmission time
  914.   Burst *b = map_->getDlSubframe()->getPdu ()->getBurst (0);
  915.   double txtime = mac_->getPhy()->getTrxTime (ch->size(), map_->getDlSubframe()->getProfile (b->getIUC())->getEncoding());
  916.   ch->txtime() = txtime;
  917.   //enqueue packet
  918.   mac_->getCManager()->get_connection (BROADCAST_CID, false)->enqueue (p);
  919. }