⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ll-ue.cc

📁 对ns2软件进行UMTS扩展
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* -*-	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 + -