📄 ll-ue.cc
字号:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* By Pablo Martin and Paula Ballester, * Strathclyde University, Glasgow. * June, 2003.*//* Copyright (c) 2003 Strathclyde University of Glasgow, Scotland. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code and binary code must contain * the above copyright notice, this list of conditions and the following * disclaimer. * * 2. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed at Strathclyde University of * Glasgow, Scotland. * * 3. The name of the University may not be used to endorse or promote * products derived from this software without specific prior written * permission. * STRATHCLYDE UNIVERSITY OF GLASGOW, MAKES NO REPRESENTATIONS * CONCERNING EITHER THE MERCHANTABILITY OF THIS SOFTWARE OR THE * SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The software * is provided "as is" without express or implied warranty of any kind.*/#include "packet.h"#include "delay.h"#include "mobilenode.h"#include "address.h"#include "arp.h"#include "queue.h"#include "cmu-trace.h"#include "mac-umts.h"#include "ll-ue.h"#include <address.h>#include "rlc-umts.h"/******************************** Timers *********************************/void AppsTimer::start(double time){ Scheduler &s = Scheduler::instance(); assert(busy_ == 0); busy_ = 1; paused_ = 0; stime = s.clock(); rtime = time; assert(rtime >= 0.0); s.schedule(this, &intr, rtime);}void AppsTimer::stop(void){ Scheduler &s = Scheduler::instance(); if(paused_ == 0) s.cancel(&intr); busy_ = 0; paused_ = 0; stime = 0.0; rtime = 0.0;}void AppsTimer::handle(Event *e){ Scheduler &s = Scheduler::instance(); busy_ = 0; paused_ = 0; stime = 0.0; rtime = 0.0; ll->AppsHandler(flow_);}//////////////////////////////////////////////////////////////////////////////////////////* TUEList Implementation *//////////////////////////////////////////////////////////////////////////////////////////TUEList:: ~TUEList(){ TimerPtr temp = Head; CurrentPtr = Head; while(CurrentPtr != NULL) {CurrentPtr = CurrentPtr->Next; delete temp; temp=CurrentPtr; }}void TUEList::AddANode(int flow){Tail->Next = new AppsTimer(ll); Tail=Tail->Next; Tail->flow_ = flow; return;}TimerPtr TUEList::Previous(TimerPtr index){TimerPtr temp=Head; if(index==Head) //special case, index IS the head :) { return Head; } while(temp->Next != index) { temp=temp->Next; } return temp;}void TUEList::DeleteANode(TimerPtr corpse){ TimerPtr temp; if(corpse == Head) //case 1 corpse = Head {temp=Head; Head=Head->Next; delete temp; } else if(corpse == Tail) //case 2 corpse is at the end { temp=Previous(corpse); temp->Next=NULL; delete corpse; Tail=temp; } else //case 3 corpse is in middle somewhere {temp=Previous(corpse); temp->Next=corpse->Next; delete corpse; } CurrentPtr=Head; //Reset the class tempptr}void TUEList::DeleteANode(int flow){ TimerPtr temp, corpse; corpse = GetNode(flow); corpse->stop(); if(corpse == Head) //case 1 corpse = Head {temp=Head; Head=Head->Next; delete temp; } else if(corpse == Tail) //case 2 corpse is at the end { temp=Previous(corpse); temp->Next=NULL; delete corpse; Tail=temp; } else //case 3 corpse is in middle somewhere {temp=Previous(corpse); temp->Next=corpse->Next; delete corpse; } CurrentPtr=Head; //Reset the class tempptr}TimerPtr TUEList::GetNode(int flow){ TimerPtr t=Head; while (t!=NULL){ if (t->flow_==flow){ return t; } t=t->Next; } return NULL;}void TUEList::start(int flow, double time){ TimerPtr corpse; corpse = GetNode(flow); corpse->stop(); corpse->start(time); return;}void TUEList::stop(int flow){ TimerPtr corpse; corpse = GetNode(flow); corpse->stop(); return;} /*********************************** Class LLUE ***********************************/// TCL classstatic class LLUEClass : public TclClass {public: LLUEClass() : TclClass("LL/UE") {} TclObject* create(int, const char*const*) { return (new LLUE); }} class_llue;int LLUE::verbose_ = {0};// constructorLLUE::LLUE() : LL(), ue_state_(0), phy_(0), rlc_(0), ifq_(0){ int i, j; bind("verbose_", &verbose_); ue_address_ = 0; for (i=0; i<MAX_NUM_FLOWS; i++) { q_[i] = new PacketQueue(); } for (i=0; i<MAX_NUM_FLOWS; i++) { 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; } handover_ = 0; freq_ = 0; appstimer_ = new TUEList(this);}int LLUE::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 3) { if (strcmp(argv[1], "phy") == 0) { phy_ = (PhyUmts*) TclObject::lookup(argv[2]); assert(phy_); phy_->tti() = ifq_->tti(); mac_->tti() = ifq_->tti(); return (TCL_OK); } if (strcmp(argv[1], "rlc") == 0) { rlc_ = (RlcUmts*) TclObject::lookup(argv[2]); assert(rlc_); return (TCL_OK); } if (strcmp(argv[1], "ifq") == 0) { ifq_ = (FCQueue*) TclObject::lookup(argv[2]); assert(ifq_); return (TCL_OK); } } else if (argc == 2) { if (strcmp(argv[1], "phy") == 0) { tcl.resultf("%s", phy_->name()); return (TCL_OK); } if (strcmp(argv[1], "rlc") == 0) { tcl.resultf("%s", rlc_->name()); return (TCL_OK); } if (strcmp(argv[1], "ifq") == 0) { tcl.resultf("%s", ifq_->name()); return (TCL_OK); } } return LL::command(argc, argv);}void LLUE::recv(Packet* p, Handler* /*h*/){ int i, pos; hdr_cmn *ch = HDR_CMN(p); hdr_ll *lh = HDR_LL(p); hdr_phy *ph = HDR_PHY_UMTS(p); hdr_ip *ih = HDR_IP(p); Scheduler& s = Scheduler::instance(); if (ch->direction() == hdr_cmn::UP){ switch (ch->channel_t()) { case CCCH: // CCCH logical channel if (lh->lltype() == LL_SETUP_REPLY) { // setup or handover procedure response ue_state_ = 2; // change the UE state in RRC layer phy_->ue_state_ = 2; // change the UE state in physical layer ue_address_ = phy_->ue_address_; // take the UE physical address MobileNode * node_ = (MobileNode*)(phy_->netif_->node()); ip_ue_ = node_->address(); // take the UE IP address phy_->ip_ue_ = ip_ue_; ifq_->ip_ue_ = ip_ue_; rlc_->addr() = ip_ue_; // give the UE IP address to RLC layer nodeb_address_ = phy_->nodeb_address_; // take the Node B physical address ip_nodeb_ = ih->saddr(); // take the Node B IP address rlc_->ip_nodeb() = ip_nodeb_; // give the Node B IP address to RLC layer if (verbose_) printf("UE %d at %f RRC: SWITCH ON--------------\n", ip_ue_, NOW); Packet::free(p); p = NULL; break; } else if (lh->lltype() == LL_FAILURE) { if (ch->ptype() == PT_RRC_FAILURE) { // flow already running // error in the connection, flow refused!!! for (i=0; i<MAX_NUM_FLOWS; i++) { if ((ih->flowid() == apps_[i].flowid_) && (apps_[i].wait_ == 0)){ // remove resources in RRC layer apps_[i].flowid_ = -1; apps_[i].wait_ = -1; apps_[i].rate_ = -1; apps_[i].sf_ = -1; apps_[i].user_rate_ = -1; apps_[i].c_coding_ = CONV_HALF; apps_[i].interval_ = -1; // remove the timer to the list of timers appstimer_->DeleteANode(ih->flowid()); // delete flow in RLC layer rlc_->remove_flow(ih->flowid()); // remove resources in IFQ ifq_->reg(ih->flowid(),0.0); // remove resources in physical layer update_phy_bytes_slot(); // drop packets stored while (q_[i]->length() > 0) { Packet::free(p); p = NULL; } break; } } } // connection with nodeb has been impossible. phy_->handover_ = 0; // end of handover procedure if (verbose_) printf("UE %d at %f RRC: Imposible to connect. UE out of coverage\n", ip_ue_, NOW); break; } else if (lh->lltype() == LL_RELEASE_REPLY) { // an application has finnished if (verbose_) printf("UE %d at %f RRC: LL_RELEASE_REPLY received\n", ip_ue_, NOW); remove_flow(p); // remove resources return; } else if (lh->lltype() == LL_RELEASE_REQ) { // an application has finnished if (verbose_) printf("UE %d at %f RRC: LL_RELEASE_REQ received\n", ip_ue_, NOW); rlc_->remove_flow(ih->flowid()); // remove resources in RLC layer send_release_reply(p); // send the release reply message return; } else if (lh->lltype() == LL_RES_REPLY) { if (ch->ptype() != PT_RRC_FAILURE) { // resources allocated for that flow in Node B freq_ = ph->freq(); // take the new frequence // look for that flow and update arrays if (verbose_) printf("UE %d at %f RRC: LL_RES_REPLY received for allocating resources of flowid %d\n", ip_ue_, NOW, ih->flowid()); for (i=0; i<MAX_NUM_FLOWS; i++) { if ((ih->flowid() == apps_[i].flowid_) && (apps_[i].wait_ == 0)){ // update fields apps_[i].wait_ = 1; double bytes = get_bytes(i); // get bytes for IFQ ifq_->reg(ih->flowid(), bytes); // register the flow in IFQ update_phy_bytes_slot(); // calculate bytes in physical layer // send the packets stored in the queue while (q_[i]->length() > 0) { send_msg(q_[i]->deque()); } break; } } } else { // FAILURE! We don't have resources if (verbose_) printf("UE %d at %f RRC: LL_RES_REPLY FAILURE received for flowid %d\n", ip_ue_, NOW, ih->flowid()); for (i=0; i<MAX_NUM_FLOWS; i++) { if ((ih->flowid() == apps_[i].flowid_) && (apps_[i].wait_ == 0)){ // remove resources in RRC layer apps_[i].flowid_ = -1; apps_[i].dest_ = -1; apps_[i].wait_ = -1; apps_[i].rate_ = -1; apps_[i].sf_ = -1; apps_[i].user_rate_ = -1; apps_[i].c_coding_ = CONV_HALF; apps_[i].interval_ = -1; // remove the timer to the list of timers appstimer_->DeleteANode(ih->flowid()); // delete flow in RLC layer rlc_->remove_flow(ih->flowid()); // drop packets stored while (q_[i]->length() > 0) { Packet::free(p); p = NULL; } break; } } } } Packet::free(p); p = NULL; break; case DTCH: // dedicated data logical channel // data packet for the application has arrived, going up. if (verbose_) printf("UE %d at %f RRC: pkt arrived with uid:%d and size: %d, to the APPLICATION\n", ip_ue_, NOW, ch->uid(), ch->size()); s.schedule(uptarget_, p, delay_); // send the packet up through the scheduler break; case TO_RRC: // directives from physical layer if (lh->lltype() == LL_PAGING) { // for paging procedure if (ph->da() == ue_address_) { // check if the paging is for me hdr_rlc_umts *rh = HDR_RLC_UMTS(p); // check if we are in handover procedure if (handover_){ rlc_->handover(1); // update resources in RLC layer handover_ = 0; } // register the new flow in RLC layer update_flow(rh->ack(), rh->frag(), ih->flowid()); // give the new downlink frequence to physical layer phy_->dlfreq = ph->freq(); send_paging_ok(p); // send paging response } return; } if (lh->lltype() == LL_HANDOVER) { // for handover procedure phy_->handover_ = 1; // update handover variable in physical layer handover_ = 1; // update handover variable in RRC layer send_setup(); // begin cell search procedure Packet::free(p); p = NULL; return; } if (ch->ptype() == PT_RRC_FAILURE) { // It has been impossible to send the RACH message because // - we have not received response to the preamble or // - we have not found available resources to send the message for (i=0; i<MAX_NUM_FLOWS; i++) { if ((ih->flowid() == apps_[i].flowid_) && (apps_[i].wait_ == 0)){ // remove resources in RRC layer apps_[i].flowid_ = -1; apps_[i].dest_ = -1; apps_[i].wait_ = -1; apps_[i].rate_ = -1; apps_[i].sf_ = -1; apps_[i].user_rate_ = -1; apps_[i].c_coding_ = CONV_HALF; apps_[i].interval_ = -1; // remove timer from the list of timers appstimer_->DeleteANode(ih->flowid()); // delete flow in RLC layer rlc_->remove_flow(ih->flowid()); // drop packets stored in the queue while (q_[i]->length() > 0) { Packet::free(p); p = NULL; } break; } } return; } default: Packet::free(p); p = NULL; } return; // direction DOWN } else { if (ue_state_ != 2){ // the mobile is not already switched ON, drop packets if (verbose_) printf("UE %d at %f RRC: pkt dropped because UE is in state %d\n",ue_address_, ue_state_); Packet::free(p); p = NULL; } else { // the mobile is switched ON i = detect_flow(p); // process the packet if (i == 0) { // the flow has been refused, drop the packet if (verbose_) printf("UE %d at %f RRC: ERROR: Flow refused\n", ip_ue_, NOW); Packet::free(p); p = NULL; } } } return;}// calculate the needed spreading factor for a given rateint get_sf(double rate){ double index = rate * UMTS_SlotTime /8; // bytes per slot in physical layer if (index > 0) { index = (320 / index); index = (int)(log(index)/log(2)); int i, r, sf_ = 2; if (index > 9) index = 9; // the highest spreading factor is 256 if (index < 2) index = 2; // the lowest spreading factor is 4 for (i=0; i<((int)index - 1); i++) { sf_ *= 2; } return(sf_); } else return(0);}// check if the packet received is part of a current applicationint LLUE::detect_flow(Packet* p){ int i; hdr_ip *ih = HDR_IP(p); hdr_cmn *ch = HDR_CMN(p); // look for the flow for (i=0; i<MAX_NUM_FLOWS; i++){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -