📄 ssscheduler.cc
字号:
/* This software was developed at the National Institute of Standards and * Technology by employees of the Federal Government in the course of * their official duties. Pursuant to title 17 Section 105 of the United * States Code this software is not subject to copyright protection and * is in the public domain. * NIST assumes no responsibility whatsoever for its use by other parties, * and makes no guarantees, expressed or implied, about its quality, * reliability, or any other characteristic. * <BR> * We would appreciate acknowledgement if the software is used. * <BR> * NIST ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND * DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING * FROM THE USE OF THIS SOFTWARE. * </PRE></P> * @author rouil */#include "ssscheduler.h"#include "burst.h"/** * Tcl hook for creating SS scheduler */static class SSschedulerClass : public TclClass {public: SSschedulerClass() : TclClass("WimaxScheduler/SS") {} TclObject* create(int, const char*const*) { return (new SSscheduler()); }} class_ssscheduler;/* * Create a scheduler */SSscheduler::SSscheduler (): t1timer_(0),t2timer_(0),t6timer_(0), t12timer_(0), t21timer_(0), lostDLMAPtimer_(0), lostULMAPtimer_(0), t44timer_(0), scan_info_(0){ debug2 ("SSscheduler created\n");}/** * Initializes the scheduler */void SSscheduler::init (){ WimaxScheduler::init(); //At initialization, the SS is looking for synchronization mac_->setMacState (MAC802_16_WAIT_DL_SYNCH); mac_->getPhy()->setMode (OFDM_RECV); //start timer for expiration t21timer_ = new WimaxT21Timer (mac_); t21timer_->start (mac_->macmib_.t21_timeout); //creates other timers t1timer_ = new WimaxT1Timer (mac_); t12timer_ = new WimaxT12Timer (mac_); t2timer_ = new WimaxT2Timer (mac_); lostDLMAPtimer_ = new WimaxLostDLMAPTimer (mac_); lostULMAPtimer_ = new WimaxLostULMAPTimer (mac_); nb_scan_req_ = 0; scan_info_ = (struct scanning_structure *) malloc (sizeof (struct scanning_structure)); memset (scan_info_, 0, sizeof (struct scanning_structure)); scan_info_->nbr = NULL; scan_info_->substate = NORMAL;}/** * Interface with the TCL script * @param argc The number of parameter * @param argv The list of parameters */int SSscheduler::command(int argc, const char*const* argv){ if (argc == 2) { if (strcmp(argv[1], "send-scan") == 0) { send_scan_request(); return TCL_OK; } } return TCL_ERROR;}/** * Start a new frame */void SSscheduler::start_dlsubframe (){ //mac_->debug ("At %f in Mac %d SS scheduler dlsubframe expires %d\n", NOW, mac_->addr(), scan_info_->substate); mac_->frame_number_++; switch (scan_info_->substate) { case SCAN_PENDING: if (scan_info_->count == 0) { resume_scanning(); return; } scan_info_->count--; break; case HANDOVER_PENDING: if (scan_info_->handoff_timeout == 0) { assert (scan_info_->nbr);#ifdef USE_802_21 mac_->debug ("At %f in Mac %d link handoff proceeding\n", NOW, mac_->addr()); mac_->send_link_handoff_proceeding (mac_->addr(), mac_->getPeerNode_head()->getPeerNode(), scan_info_->nbr->getID());#endif scan_info_->substate = HANDOVER; //restore previous state //mac_->restore_state (scan_info_->nbr->getState()->state_info); mac_->setChannel (scan_info_->nbr->getState()->state_info->channel); lost_synch (); //add target as peer mac_->addPeerNode (new PeerNode(scan_info_->nbr->getID())); return; } scan_info_->handoff_timeout--; break; default: break; } //change state of PHY //mac_->getPhy()->setMode (OFDM_RECV); //this is the begining of new frame map_->setStarttime (NOW); //start handler of dlsubframe map_->getDlSubframe()->getTimer()->sched (0); //reschedule for next frame dl_timer_->resched (mac_->getFrameDuration());}/** * Start a new frame */void SSscheduler::start_ulsubframe (){ //mac_->debug ("At %f in Mac %d SS scheduler ulsubframe expires\n", NOW, mac_->addr()); //change state of PHY: even though it should have been done before //there are some cases where it does not (during scanning) mac_->getPhy()->setMode (OFDM_SEND); //1-Transfert the packets from the queues in Connections to burst queues Burst *b; OFDMPhy *phy = mac_->getPhy(); //printf ("SS has %d ul bursts\n", map_->getUlSubframe()->getNbPdu ()); PeerNode *peer = mac_->getPeerNode_head(); //this is the BS assert (peer!=NULL); for (int index = 0 ; index < map_->getUlSubframe()->getNbPdu (); index++) { b = map_->getUlSubframe()->getPhyPdu (index)->getBurst (0); if (b->getIUC()==UIUC_END_OF_MAP) { //consistency check.. assert (index == map_->getUlSubframe()->getNbPdu ()-1); break; } if (b->getIUC()==UIUC_INITIAL_RANGING || b->getIUC()==UIUC_REQ_REGION_FULL) continue; int duration = 0; //get the packets from the connection with the same CID //printf ("\tBurst CID=%d\n", b->getCid()); Connection *c=mac_->getCManager ()->get_connection (b->getCid(), true); //assert (c); if (!c) continue; //I do not have this CID. Must be for another node //transfert the packets until it reaches burst duration or no more packets assert (c->getType()==CONN_PRIMARY); if (peer->getBasic()!= NULL) duration = transfer_packets (peer->getBasic(), b, duration); if (peer->getPrimary()!= NULL) duration = transfer_packets (peer->getPrimary(), b, duration); if (peer->getSecondary()!= NULL) duration = transfer_packets (peer->getSecondary(), b, duration); if (peer->getOutData()!=NULL) duration = transfer_packets (peer->getOutData(), b, duration); } //2-compute size of data left to create bandwidth requests if (peer->getBasic()!= NULL) create_request (peer->getBasic()); if (peer->getPrimary()!= NULL) create_request (peer->getPrimary()); if (peer->getSecondary()!= NULL) create_request (peer->getSecondary()); if (peer->getOutData()!=NULL) create_request (peer->getOutData()); //start handler for ulsubframe b = map_->getUlSubframe()->getPhyPdu (0)->getBurst (0); map_->getUlSubframe()->getTimer()->sched (b->getStarttime()*phy->getSymbolTime()); //reschedule for next frame ul_timer_->resched (mac_->getFrameDuration()); }/** * Create a request for the given connection * @param con The connection to check */void SSscheduler::create_request (Connection *con){ if (con->queueLength()==0) return; //queue is empty else if (map_->getUlSubframe()->getBw_req()->getRequest (con->get_cid())!=NULL) { debug2 ("At %f in Mac %d already pending requests for cid=%d\n", NOW, mac_->addr(), con->get_cid()); return; //there is already a pending request } Packet *p= mac_->getPacket(); hdr_cmn* ch = HDR_CMN(p); bw_req_header_t *header = (bw_req_header_t *)&(HDR_MAC802_16(p)->header); header->ht=1; header->ec=1; header->type = 0; //incremental..to check meaning header->br = con->queueByteLength(); header->cid = con->get_cid(); double txtime = mac_->getPhy()->getTrxTime (ch->size(), map_->getUlSubframe()->getProfile (UIUC_REQ_REGION_FULL)->getEncoding()); ch->txtime() = txtime; map_->getUlSubframe()->getBw_req()->addRequest (p, con->get_cid(), con->queueByteLength()); debug2 ("SSscheduler enqueued request for cid=%d len=%d\n", con->get_cid(), con->queueByteLength()); //start timeout for request}/** * Process a packet received by the Mac. Only scheduling related packets should be sent here (BW request, UL_MAP...) * @param p The packet to process */void SSscheduler::process (Packet * p){ assert (mac_ && HDR_CMN(p)->ptype()==PT_MAC); debug2 ("SSScheduler received packet to process\n"); hdr_mac802_16 *wimaxHdr = HDR_MAC802_16(p); gen_mac_header_t header = wimaxHdr->header; //we cast to this frame because all management frame start with //a type mac802_16_dl_map_frame *frame = (mac802_16_dl_map_frame*) p->accessdata(); switch (frame->type) { case MAC_DL_MAP: map_->setStarttime (NOW-HDR_CMN(p)->txtime()); //printf ("At %f frame start at %f\n", NOW, map_->getStarttime()); process_dl_map (frame); break; case MAC_DCD: process_dcd ((mac802_16_dcd_frame*)frame); break; case MAC_UL_MAP: process_ul_map ((mac802_16_ul_map_frame*)frame); break; case MAC_UCD: process_ucd ((mac802_16_ucd_frame*)frame); break; case MAC_RNG_RSP: process_ranging_rsp ((mac802_16_rng_rsp_frame*) frame); break; case MAC_REG_RSP: process_reg_rsp ((mac802_16_reg_rsp_frame*) frame); break; case MAC_MOB_SCN_RSP: process_scan_rsp ((mac802_16_mob_scn_rsp_frame *) frame); break; case MAC_MOB_BSHO_RSP: process_bsho_rsp ((mac802_16_mob_bsho_rsp_frame *) frame); break; case MAC_MOB_NBR_ADV: process_nbr_adv ((mac802_16_mob_nbr_adv_frame *) frame); break; default: mac_->debug ("unknown packet in SS %d\n", mac_->addr()); //exit (0); } Packet::free (p);}/** * Return the type of STA this scheduler is good for * @return STA_SS */station_type_t SSscheduler::getNodeType (){ return STA_MN;}/** * Called when lost synchronization */void SSscheduler::lost_synch (){ //reset timers if (t1timer_->busy()!=0) t1timer_->stop(); if (t12timer_->busy()!=0) t12timer_->stop(); if (t21timer_->busy()!=0) t21timer_->stop(); if (lostDLMAPtimer_->busy()!=0) lostDLMAPtimer_->stop(); if (lostULMAPtimer_->busy()!=0) lostULMAPtimer_->stop(); if (t2timer_->busy()!=0) t2timer_->stop(); if (t44timer_ && t44timer_->busy()!=0) t44timer_->stop(); //we need to go to receiving mode //printf ("Set phy to recv %x\n", mac_->getPhy()); mac_->getPhy()->setMode (OFDM_RECV); if (mac_->getMacState()==MAC802_16_CONNECTED) { //remove possible pending requests map_->getUlSubframe()->getBw_req()->removeRequests(); #ifdef USE_802_21 mac_->debug ("At %f in Mac %d, send link down\n", NOW, mac_->addr()); mac_->send_link_down (mac_->addr(), RC_FAIL_NORESOURCE);#endif } //remove information about peer node if (mac_->getPeerNode_head()) mac_->removePeerNode (mac_->getPeerNode_head()); //start waiting for DL synch mac_->setMacState (MAC802_16_WAIT_DL_SYNCH); t21timer_->start (mac_->macmib_.t21_timeout); if (dl_timer_->status()==TIMER_PENDING) dl_timer_->cancel(); map_->getDlSubframe()->getTimer()->reset(); if (ul_timer_->status()==TIMER_PENDING) ul_timer_->cancel(); map_->getUlSubframe()->getTimer()->reset();} /** * Called when a timer expires * @param The timer ID */void SSscheduler::expire (timer_id id){ switch (id) { case WimaxT21TimerID: mac_->debug ("At %f in Mac %d, synchronization failed\n", NOW, mac_->addr()); //go to next channel mac_->nextChannel(); t21timer_->start (mac_->macmib_.t21_timeout); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -