📄 phy-umts-nodeb.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 "connector.h"#include "packet.h"#include "random.h"#include "mobilenode.h"#include "address.h"#include <unistd.h>#include "arp.h"#include "ll.h"#include "rlc-umts.h"#include "queue.h"#include "mac.h"#include "phy-umts.h"#include "phy-umts-nodeb.h"#include "cmu-trace.h"// TCL class for PhyUmtsNodeBstatic class PhyUmtsNodebClass : public TclClass {public: PhyUmtsNodebClass() : TclClass("Phy/UmtsNodeB") {} TclObject* create(int, const char*const*) { return (new PhyUmtsNodeb()); }} class_phy_nodeb_umts;// variablesdouble PhyUmtsNodeb::slot_time_ = 0;double PhyUmtsNodeb::aich_slot_time_ = 0;int PhyUmtsNodeb::verbose_ = {0};static int PhyNodeBIndex_ = 1000;//constructorPhyUmtsNodeb::PhyUmtsNodeb() : LinkDelay(), pDownSlot_(this), pAichSlot_(this), pTxPkt_(this), pRxPkt_(this), pPaging_(this), pBler_(this), downtarget_(0), uptarget_(0), ll_(0){ int i,j; bind("verbose_", &verbose_); nodeb_address_ = PhyNodeBIndex_++; pkttoTx_= new PacketQueue(); aichtoTx_= new PacketQueue(); pchtoTx_= new PacketQueue(); pch_recv_ = NULL; paging_temp_ = new PacketQueue(); slot_time_= 0.000667 ;//umts slot is of 666.6 microseconds aich_slot_time_= 0.00125 ;//umts slot is of 1.25 miliseconds tx_rate = (int) ((8*80) / slot_time_) ; radio_active_ = 0; tti_ = 0.0; ip_nodeb_ = -1; wait_ = 0; for (i=0; i<MAX_NUM_SCRAM; i++) { for (j=0; j< MAX_NUM_SIG + 1; j++) { w_control.free_res_[i][j] = 0; } }/* for (i=0; i< MAX_NUM_SCRAM -1; i++) { w_control.dl_scramb_[i] = 0; }*/ for (i=0; i< MAX_NUM_RACH; i++) { w_control.free_rach_[i] = 0; } w_control.p_scrambling_ = nodeb_address_ + 1000; for (j=0; j<MAX_NUM_UE; j++){ data_temp_[j] = new PacketQueue(); } for (j=0; j<MAX_NUM_UE; j++){ ue_id[j] = -1; error[j] = 1000000000; addr[j] = -1; } for (j=0; j<MAX_NUM_UE; j++){ ue_info_[j].paging_group = -1; ue_info_[j].bytes_slot = 0.0; ue_info_[j].in_seq_ = 0; ue_info_[j].count = 0; ue_info_[j].ul_ErrorRate = 1000000000; ue_info_[j].lastRate = 0; ue_info_[j].Prx = 0; ue_info_[j].ul_freq = -1; ue_info_[j].nSamples = 0; ue_info_[j].IntPower = 0; } for (j=0; j<MAX_NUM_UE; j++){ for (i=0; i<MAX_NUM_DPDCH; i++){ rx_dpdch[j][i] = NULL; } } for (j=0; j<MAX_NUM_FREQ; j++){ Ioth[j] = 0; noIoth[j] = 0; } BTable = new BlerTable(); intr1_ = intr_ ; //reqd for the slot timers intr = intr_ ; intrb = intr_; // start timers pDownSlot_.start((Packet *) (& intr_), 0); pAichSlot_.start((Packet *) (& intr1_), 0); pBler_.start((Packet *) (& intrb), 0);}int PhyUmtsNodeb::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 3) { if (strcmp(argv[1], "log-target") == 0) { logtarget_ = (NsObject*) TclObject::lookup(argv[2]); if(logtarget_ == 0) return TCL_ERROR; return TCL_OK; } if (strcmp(argv[1], "ll") == 0) { ll_ = (LL*) TclObject::lookup(argv[2]); assert(ll_); return (TCL_OK); } if (strcmp(argv[1], "mac") == 0) { mac_ = (Mac*) TclObject::lookup(argv[2]); assert(mac_); return (TCL_OK); } if (strcmp(argv[1], "netif") == 0) { netif_ = (Phy*) TclObject::lookup(argv[2]); return TCL_OK; } if (strcmp(argv[1], "down-target") == 0) { downtarget_ = (NsObject*) TclObject::lookup(argv[2]); return (TCL_OK); } if (strcmp(argv[1], "up-target") == 0) { uptarget_ = (NsObject*) TclObject::lookup(argv[2]); return (TCL_OK); } } else if (argc == 2) { if (strcmp(argv[1], "down-target") == 0) { tcl.resultf("%s", downtarget_->name()); return (TCL_OK); } if (strcmp(argv[1], "up-target") == 0) { tcl.resultf("%s", uptarget_->name()); return (TCL_OK); } } return LinkDelay::command(argc, argv);}// checks the number of dpdch receivedint PhyUmtsNodeb::n_rx_dpdch(int id){ int i, n = 0; for (i=0 ; i < MAX_NUM_DPDCH ; i++) { if (rx_dpdch[id][i] != NULL) n++; } return (n); // number of dpdch received and stored of a user}// check if the packet is for this Node Bint PhyUmtsNodeb::packet_for_me(Packet* p){ int i; hdr_phy *ph = HDR_PHY_UMTS(p); i = look_for(ph->sa()); // checks if the user is in its table of addresses if (i != -1){ // the user is already registered ph->sa() = i; // change the user address with the internal addressing return (1); } // the user is not registered if (ph->first_access_ == 1){ // if the first access of that user: setup or handover for (i=0; i<MAX_NUM_UE; i++){ if (ue_id[i] < 0){ // registered the user in the table of addresses ue_id[i] = ph->sa(); ph->sa() = i; // change the user address with the internal addressing if (verbose_==1) printf("Nodeb %d at %f PHY: registering UE with phyaddr %d\n", ip_nodeb_, NOW, ue_id[i]); return (1); } } } // the user is not registered in our cell return (0);}// process the packets received from the air interfacevoid PhyUmtsNodeb::recv_from_phy(Packet* p, Handler *h){ int i, j, len; hdr_cmn *ch = HDR_CMN(p); hdr_phy *ph = HDR_PHY_UMTS(p); if (ch->error() == 1) { // if the packet is erroneus drop packet Packet::free(p); p = NULL; return; } switch (ch->channel_t()) { case PRACH: // it can be a RACH preamble or a RACH message if (ch->ptype_ == PT_PREAMBLE){ // RACH preamble received if (verbose_==1) printf("Nodeb %d at %f PHY: preamble from UE phyaddr %d and signature %d\n",ip_nodeb_, NOW, ph->sa(), ph->signature_); if (w_control.free_res_[ph->scrambling_c_][ph->signature_] == 0) { // store the signature used by the preamble to use it in AICH sig_ue_[ph->sa()] = ph->signature_; tx_aich(p); // transmit AICH message } else { // the signature was not free Packet::free(p); break; } } else { // message RACH // RACH control part, we don't need it, so drop it if ((ph->sf_ == 256) && (ph->k_ == 16 * sig_ue_[ph->sa()] + 15)) { Packet::free(p); p = NULL; break; } else { // RACH data part if (ph->bofsec_ == 1) { // begin of RACH data part, check if the resources were free if (w_control.free_res_[ph->scrambling_c_][0] == 0) { // the resources were free, allocate them w_control.free_res_[ph->scrambling_c_][0] == 1; // now the resources are not available // check if is the paging response hdr_ll *lh = HDR_LL(p); if (lh->paging_ok_) { // is a paging response, take the paging message stored hdr_phy *php = HDR_PHY_UMTS(pch_recv_); if (ue_id[ph->sa()] == php->da()){ // is the paging response expected if (verbose_==1) printf("Nodeb %d at %f PHY: Paging_ok_ rec from UE phyaddr %d\n", ip_nodeb_, NOW, ph->sa()); pPaging_.stop(); // stop the paging timer // empty pch queue while(pchtoTx_->length() > 0) { Packet::free(pchtoTx_->deque()); } wait_ = 0; // to begin more paging procedures ch->channel_t() = RACH; // ch mapping uptarget_->recv(p, this); // send to MAC Packet::free(pch_recv_); pch_recv_ = NULL; // check if there is other rach waiting to be transmited if (paging_temp_->length() > 0){ wait_ = 1; // take other PCH, and begin paging request pch_recv_ = paging_temp_->deque(); tx_pich(pch_recv_->copy()); // transmit PICH } break; } else { // is not the response expected, drop packet Packet::free(p); p = NULL; } } } else { Packet::free(p); break; }// if (verbose_==1)// printf("Nodeb %d at %f PHY: rach with sf %d, k %d\n", ip_nodeb_, NOW,ph->sf_, ph->k_); ch->channel_t() = RACH; // ch mapping ph->sa_ = ue_id[ph->sa()]; // change the source address uptarget_->recv(p, this); // send the RACH to MAC } else { // is the end of RACH message if (ph->eofsec_ == 1){ // free resources w_control.free_res_[ph->scrambling_c_][0] == 0; } Packet::free(p); p = NULL; } } } break; case DPCCH: if (verbose_==1) printf("Nodeb %d at %f PHY: DPCCH arrived with %d DPDCHs and rx power %e\n", ip_nodeb_, NOW, ph->dpcch_control().n_dpdch_, ph->rx_power()); if ((ph->sf_ == 256) && (ph->k_ == 0)) { // taking power meassurement for calculating the interference ue_info_[ph->sa()].Prx = ph->rx_power(); // power ue_info_[ph->sa()].lastRate = ph->dpcch_control().dpdch_rate_; // transmission rate ue_info_[ph->sa()].nSamples ++; ue_info_[ph->sa()].IntPower += ph->rx_power(); // take number of dpdch d_control[ph->sa()].n_dpdch_ = ph->dpcch_control().n_dpdch_; len = n_rx_dpdch(ph->sa()); // check the number of dpdchs received // check if all dpdchs transmitted has been received if (len != d_control[ph->sa()].n_dpdch_){ // they have not been received, drop the dpdch stored for (j=0; j<len; j++) { Packet::free(rx_dpdch[ph->sa()][j]); rx_dpdch[ph->sa()][j] = NULL; } break; } // all dpdch has been received decode(ph->sa()); // decode the dpdchs Packet::free(p); } else { Packet::free(p); } break; case DPDCH: // store DPDCH packet in buffer in the next free possition len = n_rx_dpdch(ph->sa()); rx_dpdch[ph->sa()][len] = p; break; default: break; } return;}// receive all the packets, either with UP or DOWN directionvoid PhyUmtsNodeb::recv(Packet* p, Handler *h){ hdr_cmn *ch = HDR_CMN(p); hdr_phy *ph = HDR_PHY_UMTS(p); hdr_ll *lh = HDR_LL(p); double stime; int i,len; if (ch->direction() == hdr_cmn::UP) { // for the interference model if ((ch->channel_t() == DPCCH) && (ph->freq() < 12)){ // cpcch received in uplink frequence Ioth[ph->freq()] += ph->rx_power(); noIoth[ph->freq()]++; } if (ch->error() == 1) { // if packet with error, drops it Packet::free(p); return; } if (nodeb_address_ == ph->da()) { // if the packet is for me if (packet_for_me(p)) { // checks if the user is registered in its cell // simulation of reception time radioSwitch(ON); // turns the radio ON stime = TX_Time(p); // calculates transmission time pRxPkt_.start(p, stime); // stats reception timer } else { // the user is not register in this cell Packet::free(p); p=NULL; } } else { // the packet is not for me, drop it Packet::free(p); p=NULL; } } if (ch->direction() == hdr_cmn::DOWN) { switch (ch->channel_t()) { //case BCH: case PCH: // paging request received in PCH channel // checks if there is another paging procedure before if (wait_) { // there's another paging procedure running paging_temp_->enque(p); } else { // there is not paging procedure running wait_ = 1; pch_recv_ = p->copy(); // stores the paging message tx_pich(p); // transmits PICH } break; case FACH: // this channel is goint to be used for: // setup and handover reply, resource allocation and RLC ACK mode if (lh->lltype() == LL_SETUP_REPLY) { // setup or handover procedure ue_registry(p); // registries the new UE i = look_for(ph->da()); // looks for the UE in the addresses registry ue_info_[i].ul_freq = ph->freq(); } if (lh->lltype() == LL_RES_REPLY) { // for resource allocation i = look_for(ph->da()); ue_info_[i].ul_freq = ph->freq(); } tx_fach(p); // transmits FACH message break; case DCH: // user dedicated data channel// if (verbose_==1)// printf("Nodeb %d at %f PHY: pkt arrived at NodeB from MAC with %d and direction:%d\n", ip_nodeb_, NOW, ch->uid(), ch->direction()); dl_mux(p); // calls to the downlink multiplexing channel break; default: Packet::free(p); p = NULL; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -