📄 ll-nodeb.cc
字号:
// resources already allocated send_msg(p,i); // send packet return; } } else { // is the first pkt of that flow rx if (free_res(p)) { // in the downlink if (verbose_) printf("Nodeb %d at %f RRC: first packet of flow %d with direction DOWN received from UE %d. Giving resources\n" ,ip_nodeb_, NOW, ihp->flowid(), ihp->saddr()); if (!ue_node(ihp->saddr())) { filltype(p); // Add a timer to the list of timers removeflow_->AddANode(ihp->saddr(), ihp->daddr(), ch->size(), ihp->flowid()); // start timer removeflow_->start(ihp->saddr(), ihp->flowid(), 1.0); } pag_proc(p->copy(),i); // begin paging procedure flows_->AddANode(ihp->saddr(), ihp->daddr(), ihp->flowid(), 1); fl_->enque(p); // store packet until response return; } else { if (verbose_) printf("Nodeb %d at %f RRC: first packet DOWN of flow %d received from UE %d. No resources available\n" ,ip_nodeb_, NOW, ihp->flowid(), ihp->saddr()); refused->add(ihp->flowid()); // send failure message if (ue_node(ihp->saddr())) { // fill ll, common and ip headers lh->lltype() = LL_FAILURE; ch->ptype() = PT_RRC_FAILURE; nsaddr_t temp = ihp->daddr(); ihp->daddr() = ihp->saddr(); ihp->saddr() = temp; ihp->ttl() = 200; ch->channel_t() = FROM_RRC; // ch allocation s.schedule(uptarget_, p, delay_); // send the packet up through the scheduler return; } } } } } } if (verbose_) printf("Nodeb %d at %f RRC: pkt dropped\n",ip_nodeb_, NOW); Packet::free(p); p = NULL; break; } } return;}// registers the new UE in its internal structureint LLNodeb::register_ue(Packet* p){ int i, j; hdr_cmn *ch = HDR_CMN(p); hdr_ip *ih = HDR_IP(p); hdr_phy *ph = HDR_PHY_UMTS(p); for (i=0; i<MAX_NUM_UE; i++){ if (ue_info_[i].phyaddr_ == -1){ // register the new UE in array ue_info_[] ue_info_[i].phyaddr_ = ph->sa(); ue_info_[i].ipaddr_ = ih->saddr(); if (verbose_) printf("Nodeb %d at %f RRC: LL_SETUP received. Reistering UE %d\n" ,ip_nodeb_, NOW, ue_info_[i].ipaddr_); for (j=0; j<MAX_NUM_FLOWS; j++){ if (*ph->flows_[j][2] > 0) { // Handover: has flows already running // register flows in RLC layer update_flow(*ph->flows_[j][0],*ph->flows_[j][1],*ph->flows_[j][2], ih->saddr(),1); } else { break; } } return (1); } } return (0);}// gets bytes per tti for a specific user in IFQdouble LLNodeb::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 if (ue_info_[pos].dlsf_ > 0) { bits = 2 * (2560 / ue_info_[pos].dlsf_) * (ifq_->tti() / UMTS_SlotTime); // bits per tti sum = ue_info_[pos].dltotalr_; if (verbose_) printf("Nodeb %d at %f RRC: UE %d with DL sf %d and rate %f\n", ip_nodeb_,NOW,ue_info_[pos].ipaddr_,ue_info_[pos].dlsf_,ue_info_[pos].dltotalr_); if (sum > 0) { if (sum > 1920000) // more than one dpdch is needed bits = bits * ((int)(sum / 1920000) + 1); } bits = bits/2; // apply Convolutional Half Rate coding bits = (bits * rlcfsize) / (rlcfsize + rlchdrsize + machdrsize); if (verbose_) printf("Nodeb %d at %f RRC: ~~~~~~~~~~~~~~~ bytes_tti in IFQNodeB %f ~~~~~~~~~~~~~~\n",ip_nodeb_, NOW, bits / 8); return(bits/8); } else { return (0.0); }}// calculate and update bytes in physical layervoid LLNodeb::update_phy_bytes_slot(int pos){ double bytes_slot; if (ue_info_[pos].dltotalr_ > 0) { // bytes per slot in physical layer for the actual SF for that UE bytes_slot = (2 * (2560 / (double)ue_info_[pos].dlsf_) / 8); if (ue_info_[pos].dltotalr_ > 1920000) // case of several DPDCHs bytes_slot = bytes_slot * ((int)(ue_info_[pos].dltotalr_ / 1920000) + 1); } else { bytes_slot = 0.0; // none application for that UE } if (verbose_) printf("Nodeb %d at %f RRC: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bytes_slot in PHY %f for UE %d~~~~~~~~~~~~~~\n" ,ip_nodeb_, NOW, bytes_slot, ue_info_[pos].phyaddr_); ip_nodeb_, NOW, phy_->slot_bytes(ue_info_[pos].phyaddr_, bytes_slot); // pass the result to phy layer return;}// returns the code for applications originated in fixed nodesint LLNodeb::getcode(nsaddr_t src, int flow){ int code; // 0 TURBO, 1 CONV_HALF, 2 CONV_THIRD Node * node_ = (Node*)(phy_->netif_->node()); // get the type of channel coding for the flow int type = node_->list->lookfortype(getip(src), flow); switch (type) { case 0: // audio code = 0; break; case 1: // video code = 0; break; case 2: // mail code = 2; break; case 3: // fax code = 1; break; case 4: // speech code = 1; break; case 5: // ftp code = 0; break; case 6: // http code = 1; break; default: code = -1; break; } return code;}// calculates the spreading factor for a given packetint LLNodeb::cal_sf(Packet* p){ hdr_ll *lh = HDR_LL(p); hdr_ip *ih = HDR_IP(p); hdr_cmn *ch = HDR_CMN(p); double index; // bits per slot if (!ue_node(ih->saddr())) { // if the source is a fixed node takes the inf from list Node * node_ = (Node*)(phy_->netif_->node()); index = node_->list->lookforrate(getip(ih->saddr()), ih->flowid()); int code = getcode(ih->saddr(), ih->flowid()); // take channel coding index = phy_rate(index, code, ch->size()); // get physical rate for the application // with the channel coding already calc. index = index * UMTS_SlotTime / 8; // bytes per slot in physical layer } else { // takes the information from the packet index = lh->tx_rate() * UMTS_SlotTime / 8; // bytes per slot in physical layer } if (index > 0) { // calculate the SF for that physical rate index = (2*320 / index); index = (int)(log(index)/log(2)); int i, r, sf_ = 2; if (index > 9) index = 9; if (index < 2) index = 2; for (i=0; i<((int)index - 1); i++) { sf_ *= 2; } if (verbose_) printf("Nodeb %d at %f RRC: the DL SF given is %d\n", ip_nodeb_, NOW,sf_); return(sf_); } else return(0);}// calculates the spreading factor for a given physical rateint LLNodeb::cal_sf(double rate){ double index; // bits per slot index = rate * UMTS_SlotTime / 8; // bytes per slot in physical layer if (index > 0) { // calculate the SF for that physical rate index = (2*320 / index); index = (int)(log(index)/log(2)); int i, r, sf_ = 2; if (index > 9) index = 9; if (index < 2) index = 2; for (i=0; i<((int)index - 1); i++) { sf_ *= 2; } if (verbose_) printf("Nodeb %d at %f RRC: the DL SF given is %d\n", ip_nodeb_, NOW,sf_); return(sf_); } else return(0);}// allocate resources in the OSVF treesint LLNodeb::alloc_res(Packet* p, int sf){ hdr_ip *ih = HDR_IP(p); int i, r; if (verbose_) printf("\nNodeb %d at %f RRC: Trying to give sf %d from OVSF trees\n", ip_nodeb_, NOW,sf); int j = Random::integer(MAX_NUM_FREQ-1); for (i=0; i<MAX_NUM_FREQ; i++) { // for any frequencies if (dl_sftree[j]->insert_sf(getip(ih->daddr()), sf)) {// allocate resources r = look_for(ih->daddr()); ue_info_[r].dlsf_ = sf; // update SF for that UE ue_info_[r].dlfreq_ = j + 12; // update freq for that UE (downlink) return(1); } j++; if (j == MAX_NUM_FREQ) j = 0; } return(0);}// remove resources in the OSVF treesint LLNodeb::remove_res(int pos){ int i; if (verbose_) printf("Nodeb %d at %f RRC: Removing UE %d with sf %d and freq %d from OSVF\n", ip_nodeb_, NOW,ue_info_[pos].ipaddr_, ue_info_[pos].dlsf_,ue_info_[pos].dlfreq_ - 12); if (dl_sftree[ue_info_[pos].dlfreq_ - 12]->remove_sf(ue_info_[pos].ipaddr_, ue_info_[pos].dlsf_)) { // resources removed successfully return(1); } // resuorces not removed successfully return(0);}// remove downlink resources allocated for that flowvoid LLNodeb::remove_flow_dl(Packet* p){ hdr_ip *ihp = HDR_IP(p); hdr_phy *ph = HDR_PHY_UMTS(p); hdr_ll *lh = HDR_LL(p); int temp; int i = look_for(ihp->saddr()); if (verbose_) printf("Nodeb %d at %f RRC: remove_flow_dl of UE with ip %d total rate stored %e rate in the message %e\n", ip_nodeb_, NOW, ihp->saddr(),ue_info_[i].dltotalr_,lh->tx_rate()); if (ue_info_[i].dlsf_ > 0) { // flows already allocated for that node remove_res(i); //remove downlink resources from OSVF trees rlc_->remove_flow(ihp->flowid(),ue_info_[i].ipaddr_); // remove resources in RLC layer ue_info_[i].dltotalr_ -= lh->tx_rate(); // decrease physical rate for that UE if (ue_info_[i].dltotalr_ > 0) { // there are still active flows for that UE; reallocate resources if (verbose_) printf("Nodeb %d at %f RRC: remove_flow_dl: given resources again\n", ip_nodeb_, NOW); int sf = cal_sf(ue_info_[i].dltotalr_); // recalculate the needed SF nsaddr_t tempd = ihp->daddr(); ihp->daddr() = ihp->saddr(); alloc_res(p->copy(),sf); // reallocate resources in OSVF trees ihp->daddr() = tempd; } else { // that UE has not got any other application running ue_info_[i].dltotalr_ = 0; ue_info_[i].dlsf_ = -1; } ph->sa() = ue_info_[i].phyaddr_; ifq_->reg(ihp->saddr(), get_bytes(i)); // update IFQ layer for that UE update_phy_bytes_slot(i); // update physical rate needed for that UE FListPtr ptr = flows_->GetNode(ihp->daddr(), ihp->saddr(), ihp->flowid()); if (ptr != NULL) { // delete flow from the list flows_->DeleteANode(ptr); temp = fl_->length(); while (temp > 0) { // free packets of that flow waiting for resource allocation Packet* prov; prov = fl_->deque(); struct hdr_ip *ihprov = HDR_IP(prov); if ((ihprov->flowid() == ihp->flowid()) && (ihprov->daddr() == ihp->saddr())){ drop(prov); }else fl_->enque(prov); --temp; } } } return;}// remove the uplink resources allocated for that flowvoid LLNodeb::remove_flow_ul(Packet* p, int pos){ hdr_ip *ihp = HDR_IP(p); if (verbose_) printf("Nodeb %d at %f RRC: Removing UL resources to UE %d\n" ,ip_nodeb_, NOW,ue_info_[pos].ipaddr_); rlc_->remove_flow(ihp->flowid(),ue_info_[pos].ipaddr_); // remove resources in RLC layer if (ue_info_[pos].ipaddr_ == ihp->saddr()){ // update addresses ihp->saddr() = ihp->daddr(); ihp->daddr() = ue_info_[pos].ipaddr_; } return;}// update the static structure registry_void LLNodeb::update_db(Packet* p){ int i, j; hdr_cmn *ch = HDR_CMN(p); hdr_phy *ph = HDR_PHY_UMTS(p); hdr_ip *ih = HDR_IP(p); // UE already registered (handover procedure) for (i=0; i<MAX_NUM_NODES; i++){ if (registry_[i].ue_ == ih->saddr()){ update_nodeb(p->copy(), registry_[i].nodeb_);// send a HANDOVER message to the former Nodeb registry_[i].nodeb_ = ip_nodeb_; // update the registry_ if (verbose_) printf("Nodeb %d at %f RRC: Handover procedure, ue(ip): %d updated\n" ,ip_nodeb_, NOW, getip(ih->saddr())); break; } } // UE not registered in the system (turn on procedure) if (i == MAX_NUM_NODES) { for (i=0; i<MAX_NUM_NODES; i++){ if (registry_[i].ue_ < 0){ // update registry_ registry_[i].ue_ = ih->saddr(); registry_[i].nodeb_ = ip_nodeb_; if (verbose_) printf("Nodeb %d at %f RRC: Turn on procedure, ue(ip): %d updated\n", ip_nodeb_, NOW, getip(ih->saddr())); break; } } } return;}// send a HANDOVER message to the former Nodeb for the incoming UEvoid LLNodeb::update_nodeb(Packet* p, nsaddr_t addr){ hdr_ip *ih = HDR_IP(p); hdr_ll *lh = HDR_LL(p); hdr_cmn *ch = HDR_CMN(p); // fill common and ip headers ch->direction() = hdr_cmn::DOWN; ch->channel_t() = FROM_RRC; // ch allocation ch->next_hop() = addr; ih->daddr() = addr; lh->lltype() = LL_HANDOVER; // set type of message send_to_ra(p); // send the packet to the routing agent return;}// returns the position in ue_info_[] fo that UEint LLNodeb::look_for(nsaddr_t ad){ int i; for (i=0; i<MAX_NUM_UE; i++) { if (ue_info_[i].ipaddr_ == ad) return(i); // found it } return(-1); // not found it}// returns if the UE is a fixed node (0) or a UE (1)int LLNodeb::ue_node(nsaddr_t source){ int i; int dir = getip(source); for (i=0; i<MAX_NUM_NODES; i++){ if (registry_[i].ue_ == source){ // UE return(1); } } return(0); // fixed node}// send data packets downwardsvoid LLNodeb::send_msg(Packet* p, int loc){ 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 physical, ll, rlc, common and ip headers lhp->lltype() = LL_DATA; php->sa() = phy_->nodeb_address_; php->da() = ue_info_[loc].phyaddr_; php->freq() = ue_info_[loc].dlfreq_; chp->channel_t() = DTCH; // ch allocation chp->next_hop_ = ihp->daddr(); chp->prev_hop_ = ip_nodeb_; chp->direction() = hdr_cmn::DOWN; chp->error() = 0; // if it is a flow generated in a wired node, rlc in frag mode (default) if (!ue_node(ihp->saddr())) { hdr_rlc_umts *rhp = HDR_RLC_UMTS(p); rhp->frag() = 1; rhp->bopno() = 0; rhp->rlctype() = RLC_DATA; i = getcode(ihp->saddr(), ihp->flowid()); // get channel coding switch (i){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -