📄 ll-ue.cc
字号:
if (apps_[i].flowid_ == ih->flowid()){ // flowid already registered if (apps_[i].wait_ == 1){ // resources already allocated appstimer_->start(ih->flowid(), 1.0); // start time send_msg(p->copy()); // send packet to IFQ return (1); } else if (apps_[i].wait_ == 0) { // flow waiting for resource reply appstimer_->start(ih->flowid(), 1.0); // start time q_[i]->enque(p); // store the packet in the queue until response return (1); } else { // is the first packet of that flow // calculate the physical rate that is going to send over the air interface apps_[i].rate_ = get_rate(apps_[i].user_rate_, apps_[i].c_coding_, ch->size()); // calculate the interval between two packets apps_[i].interval_ = (ch->size() * 8)/ apps_[i].user_rate_; // add a timer for this flow in the list of timers appstimer_->AddANode(ih->flowid()); appstimer_->start(ih->flowid(), 1.0); // start timer // update field of the array apps_[] apps_[i].dest_ = ih->daddr(); // spreading factor needed in physical layer apps_[i].sf_ = get_sf(apps_[i].rate_); send_res_req(p->copy(), i); // send the resource request message apps_[i].wait_ = 0; // put wait = 0 to prevent sending messages if (verbose_) printf("UE %d at %f RRC: STORING flow %d with physical rate %e and SF %d\n" ,ip_ue_, NOW, ih->flowid(),apps_[i].rate_,apps_[i].sf_); q_[i]->enque(p->copy()); // store the packet in the queue until response return (1); } } } return (0);}// for release procedure: send a release reply messagevoid LLUE::send_release_reply(Packet* p){ Scheduler& s = Scheduler::instance(); Packet *sp = p->copy(); hdr_ll *lh = HDR_LL(sp); hdr_ip *ih = HDR_IP(sp); hdr_phy *ph = HDR_PHY_UMTS(sp); hdr_cmn *ch = HDR_CMN(sp); // fill ip, common and physical headers ih->daddr() = ih->saddr(); ih->saddr() = ip_ue_; lh->lltype() = LL_RELEASE_REPLY; ph->sa() = ue_address_; ph->da() = nodeb_address_; ch->direction() = hdr_cmn::DOWN; ch->channel_t() = CCCH; // ch allocation if (verbose_) printf("UE %d at %f RRC: LL_RELEASE_REPLY sent related to the flowid %d\n", ip_ue_, NOW, ih->flowid()); s.schedule(downtarget_, sp, delay_); // send the packet down Packet::free(p); return;}// send data packets received from the application to the IFQvoid LLUE::send_msg(Packet* p){ int i; Scheduler& s = Scheduler::instance(); hdr_cmn *chp = HDR_CMN(p); hdr_ll *lhp = HDR_LL(p); hdr_ip *ihp = HDR_IP(p); hdr_phy *php = HDR_PHY_UMTS(p); // fill ll, physical and common headers lhp->lltype() = LL_DATA; for (i=0; i<MAX_NUM_FLOWS; i++) { if (ihp->flowid() == apps_[i].flowid_) { lhp->tx_rate() = apps_[i].rate_; // puts the fisical rate in the packet break; } } php->c_coding() = apps_[i].c_coding_; // channel coding chp->channel_t() = DTCH; // ch allocation chp->next_hop_ = ip_nodeb_; chp->direction() = hdr_cmn::DOWN; chp->error() = 0; if (verbose_) printf("UE %d at %f RRC: sending DATA DOWN with uid: %d to destination(ip) %d and flow %d\n", ip_ue_, NOW, chp->uid(), Address::instance().get_nodeaddr(ihp->daddr()), ihp->flowid()); s.schedule(downtarget_, p, delay_); // send the packet down through the scheduler return;}// for paging procedure: send the paging responsevoid LLUE::send_paging_ok(Packet* p){ Scheduler& s = Scheduler::instance(); hdr_ip *ih = HDR_IP(p); hdr_rlc_umts *rh = HDR_RLC_UMTS(p); Packet* sp = Packet::alloc(); hdr_ip *ihsp = HDR_IP(sp); hdr_cmn *chsp = HDR_CMN(sp); hdr_ll *lhsp = HDR_LL(sp); hdr_phy *phsp = HDR_PHY_UMTS(sp); struct hdr_rlc_umts *rhsp = HDR_RLC_UMTS(sp); // fill physical, ll, rlc, common and ip headers phsp->sa() = ue_address_; phsp->da() = nodeb_address_; phsp->c_coding() = CONV_HALF; lhsp->lltype() = LL_PAGING; lhsp->paging_ok_ = 1; // reponse ok rhsp->ack() = rh->ack(); rhsp->frag() = rh->frag(); chsp->channel_t() = CCCH; // ch allocation chsp->next_hop_ = ip_nodeb_; chsp->direction() = hdr_cmn::DOWN; chsp->error() = 0; chsp->size() = 5; ihsp->flowid() = ih->flowid(); ihsp->saddr() = ih->saddr(); ihsp->daddr() = ih->daddr(); if (verbose_) printf("UE %d at %f RRC: sending PAGING_OK\n", ip_ue_, NOW); s.schedule(downtarget_, sp, delay_); // send the packet down through the scheduler Packet::free(p); p = NULL; return;}// calculate bytes per slot in physical layer and update themvoid LLUE::update_phy_bytes_slot(void){ int i; double bytes_slot, sum = 0.0; // add the physical rates of all the applications currently running for (i=0; i<MAX_NUM_FLOWS; i++) { if (apps_[i].flowid_ != -1) { sum += apps_[i].rate_; } } if (sum > 0) { // gets the spreading factor needed for supporting the total rate bytes_slot = (2560 / get_sf(sum)) / 8; // calculate bytes in physical layer if (sum > 960000) // if more than one dpdch is requiered bytes_slot = bytes_slot * ((int)(sum / 960000) + 1); } else { // no applications running in that moment bytes_slot = 0.0; } if (verbose_) printf("UE %d at %f RRC: ~~~~~~~~~~~~~~~~~~~~~ bytes_slot in PHY %f ~~~~~~~~~~~~~~\n", ip_ue_, NOW, bytes_slot); phy_->bytes_slot = bytes_slot; // update bytes per slot in physical layer return;}// register a new application in RRC layerint LLUE::insert_flow(int flow, double rate, Chan_Coding code){ int i; for (i=0; i<MAX_NUM_FLOWS; i++) { // looks for a free position if (apps_[i].flowid_ < 0){ // update apps_[] fieds with the new information apps_[i].flowid_ = flow; apps_[i].wait_ = -1; apps_[i].user_rate_ = rate; apps_[i].c_coding_ = code; if (verbose_) printf("UE %d at %f RRC: trying to insert flow %d rate %f sf %d\n", ip_ue_, NOW, apps_[i].flowid_, apps_[i].rate_, apps_[i].sf_); return(i); } } // there is not free position, ERROR return (-1);}// bytes in ifq per ttidouble LLUE::get_bytes(int pos){ double bits, sum; int rlcfsize = rlc_->rlcfragsize(); // rlc fragment size int rlchdrsize = RLC_HDR_SZ; // rlc-umts header size int machdrsize = MAC_HDR_SZ; // mac-umts header size int phyhdrsize = PHY_HDR_SZ; // phy-umts header size bits = (2560 / apps_[pos].sf_) * (ifq_->tti() / UMTS_SlotTime); // bits per tti sum = apps_[pos].rate_; if (sum > 0) { if (sum > 960000) // more than one dpdch is required bits = bits * ((int)(sum / 960000) + 1); } bits = (bits * (rlcfsize + rlchdrsize + machdrsize)) / (rlcfsize + rlchdrsize + machdrsize + phyhdrsize); // apply decoding switch (apps_[pos].c_coding_) { case TURBO: // turbo coding bits = bits/3; break; case CONV_HALF: // convolutional half bits = bits/2; break; case CONV_THIRD: // convolutional third bits = bits/3; break; default: break; } // bytes in IFQ for an application per TTI bits = (bits * rlcfsize) / (rlcfsize + rlchdrsize + machdrsize); if (verbose_) printf("UE %d at %f RRC: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bytes_tti in IFQ %f ~~~~~~~~~~~~~~\n", ip_ue_, NOW, bits/8); return(bits/8); // bits in IFQ for that application per TTI}// calculate the physical ratedouble LLUE::get_rate(double rate, Chan_Coding code, int psize){ double rt, time; int rlcfsize = rlc_->rlcfragsize(); // rlc fragment size int rlchdrsize = RLC_HDR_SZ; // rlc-umts header size int machdrsize = MAC_HDR_SZ; // mac-umts header size int phyhdrsize = PHY_HDR_SZ; // phy-umts header size time = (psize * 8)/ rate; // time between two user packets int npkts = (int)(psize / rlcfsize); // number of rlc fragments per user packet if ((psize % rlcfsize) > 0) npkts++; rt = (npkts * rlcfsize * 8)/time; // effective user rate rt = (rt * (rlcfsize + rlchdrsize + machdrsize))/rlcfsize; // user rate before channel coding // apply channel coding switch (code) { case 0: // turbo coding rt = 3*rt; break; case 1: // convolutional half rt = 2*rt; break; case 2: // convolutional third rt = 3*rt; break; default: break; } return(rt);}// send a resource request messagevoid LLUE::send_res_req(Packet* p, int i){ Scheduler& s = Scheduler::instance(); hdr_ip *ih = HDR_IP(p); hdr_cmn *ch = HDR_CMN(p); Packet* sp = Packet::alloc(); struct hdr_cmn *chsp = HDR_CMN(sp); struct hdr_ll *lhsp = HDR_LL(sp); struct hdr_ip *ihsp = HDR_IP(sp); struct hdr_phy *phsp = HDR_PHY_UMTS(sp); // fill ll, common and ip headers lhsp->lltype() = LL_RES_REQ; lhsp->tx_rate() = apps_[i].rate_; lhsp->psize() = ch->size(); lhsp->paging_ok_ = 0; phsp->c_coding() = CONV_HALF; chsp->channel_t() = CCCH; // ch allocation chsp->next_hop_ = ip_nodeb_; chsp->direction() = hdr_cmn::DOWN; chsp->size() = 5; chsp->error() = 0; ihsp->flowid() = ih->flowid(); ihsp->saddr() = ih->saddr(); ihsp->daddr() = ih->daddr(); if (verbose_) printf("UE %d at %f RRC: sending RESOURCE_REQUEST from ue(ip): %d to ue(ip): %d\n", ip_ue_, NOW, Address::instance().get_nodeaddr(ihsp->saddr()),Address::instance().get_nodeaddr(ihsp->daddr())); s.schedule(downtarget_, sp->copy(), delay_); // send the packet down through the scheduler Packet::free(sp); sp = NULL; return;}// for setup and handover procedures: send a setup request messagevoid LLUE::send_setup(void){ Packet* sp = Packet::alloc(); struct hdr_cmn *chsp = HDR_CMN(sp); struct hdr_ll *lhsp = HDR_LL(sp); struct hdr_ip *ihsp = HDR_IP(sp); struct hdr_phy *phsp = HDR_PHY_UMTS(sp); MobileNode * node_ = (MobileNode*)(phy_->netif_->node()); Scheduler& s = Scheduler::instance(); // fill physical, ll, common and ip headers chsp->direction_ = hdr_cmn::DOWN; lhsp->tx_rate() = 0; chsp->size_=32; chsp->error()= 0; chsp->channel_t()=CCCH; // ch allocation chsp->next_hop_= -1; phsp->c_coding() = CONV_HALF; int k, i = 0; for (k=0; k<MAX_NUM_FLOWS; k++){ phsp->flows_[k][0] = new int; phsp->flows_[k][1] = new int; phsp->flows_[k][2] = new int; *phsp->flows_[k][0] = -1; *phsp->flows_[k][1] = -1; *phsp->flows_[k][2] = -1; } if (handover_){ // handover procedure for (k=0; k<MAX_NUM_FLOWS; k++){ if (apps_[k].flowid_ > 0){ // inform the new Node B about the flows already running, and their mode *phsp->flows_[i][0] = rlc_->get_acked(apps_[k].flowid_); *phsp->flows_[i][1] = rlc_->get_fraged(apps_[k].flowid_); *phsp->flows_[i][2] = apps_[k].flowid_; i++; } } } ihsp->saddr() = node_->address(); lhsp->lltype() = LL_SETUP; if (verbose_) printf("UE %d at %f RRC: Trying to Switched ON......\n", ip_ue_, NOW); s.schedule(downtarget_, sp, delay_); // send the packet down through the scheduler return;}// for switching ON the mobilevoid LLUE::switch_on(void){ ue_state_ = 1; // change the state in RRC from 0 to 1 phy_->ue_state_ = 1; // change the state in physical layer from 0 to 1 send_setup(); // begin cell search procedure return;}// register a new flow in RLC layervoid LLUE::update_flow(int acked, int fraged, int flowid){ if (verbose_) printf("UE %d at %f RRC: Update_flow: ack, frag, flowid [%d %d %d]\n", ip_ue_, NOW, acked, fraged, flowid); rlc_->store_flow(acked, fraged, flowid); // register the flow with its characteristics return;}// configure a new flow in RRC layervoid LLUE::configure_flow(int flow, const char*const& type , double rate){ int acked, fraged; Chan_Coding code; // depending on the type of application, chose the mode (ACK or non-ACK), // the channel coding and if is necessary fragmentation (default fragmentation) if (strcmp(type, "audio") == 0) { code = TURBO; // turbo coding fraged = 1; // fragmentation acked = 0; // non-ACK mode } if (strcmp(type, "video") == 0) { code = TURBO; // turbo coding fraged = 1; // fragmentation acked = 0; // non-ACK mode } if (strcmp(type, "mail") == 0) { code = CONV_THIRD; // convolutional third fraged = 1; // fragmentation acked = 1; // ACK mode } if (strcmp(type, "fax") == 0) { code = CONV_HALF; // convolutional half fraged = 1; // fragmentation acked = 0; // non-ACK mode } if (strcmp(type, "speech") == 0) { code = CONV_HALF; // convolutional half fraged = 1; // fragmentation acked = 0; // non-ACK mode } if (strcmp(type, "ftp") == 0) { code = TURBO; // turbo coding fraged = 1; // fragmentation acked = 1; // ACK mode } if (strcmp(type, "http") == 0) { code = CONV_HALF; // convolutional half fraged = 1; // fragmentation acked = 1; // ACK mode } // register the new flow with its characteristics in the apps_[] array int i = insert_flow(flow, rate, code); if (i == -1) { // too many applications in this terminal if (verbose_) printf("UE %d at %f RRC: ERROR: Trying to allocate in UE %d more than the MAX_NUM_FLOWS %d permissible\n" ,ip_ue_, NOW, MAX_NUM_FLOWS); exit(-1); } // register the new flow in RLC layer update_flow(acked, fraged, flow); return;}// remove resources allocated for a flowvoid LLUE::remove_flow(Packet* p){ int i; hdr_ip *ih = HDR_IP(p); // looks for the flow in the array for (i=0; i<MAX_NUM_FLOWS; i++) { if (apps_[i].flowid_ == ih->flowid()){ break; } } rlc_->remove_flow(apps_[i].flowid_); // remove resources from RLC ifq_->reg(apps_[i].flowid_,0.0); // remove resources from IFQ // remove resources from RRC layer apps_[i].flowid_ = -1; apps_[i].dest_ = -1; apps_[i].wait_ = -1; apps_[i].sf_ = -1; apps_[i].rate_ = -1; apps_[i].user_rate_ = -1; apps_[i].interval_ = -1; apps_[i].c_coding_ = CONV_HALF; update_phy_bytes_slot(); // remove resources from PHY Packet::free(p); p = NULL; return;}// begin the release procedurevoid LLUE::AppsHandler(int flow){ // The application has finished; // we have to send a release request to the Node B and to the node destiny Scheduler& s = Scheduler::instance(); int pos; // look for the flow for (pos=0; pos<MAX_NUM_FLOWS; pos++) { if (apps_[pos].flowid_ == flow) break; } Packet* sp = Packet::alloc(); struct hdr_cmn *chsp = HDR_CMN(sp); struct hdr_ll *lhsp = HDR_LL(sp); struct hdr_ip *ihsp = HDR_IP(sp); struct hdr_phy *phsp = HDR_PHY_UMTS(sp); // fill physical, ll, common and ip headers lhsp->lltype() = LL_RELEASE_REQ; lhsp->tx_rate() = apps_[pos].rate_; lhsp->paging_ok_ = 0; phsp->sa() = ue_address_; phsp->da() = nodeb_address_; phsp->c_coding() = CONV_HALF; chsp->channel_t() = CCCH; // ch allocation chsp->next_hop_ = ip_nodeb_; chsp->direction() = hdr_cmn::DOWN; chsp->size() = 5; chsp->error() = 0; ihsp->flowid() = apps_[pos].flowid_; ihsp->saddr() = ip_ue_; ihsp->daddr() = apps_[pos].dest_; if (verbose_) printf("\nUE %d at %f RRC: ******************* sending RELEASE_REQ to ue(ip): %d\n", ip_ue_, NOW, Address::instance().get_nodeaddr(ihsp->daddr())); s.schedule(downtarget_, sp->copy(), delay_); // send the packet down through the scheduler Packet::free(sp); sp = NULL; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -