diff -urN ns-2.30-orig/EURANE-version ns-2.30-eu112/EURANE-version
--- ns-2.30-orig/EURANE-version	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/EURANE-version	2006-10-08 00:45:47.000000000 +0307
@@ -0,0 +1 @@
+EURANE version 1.12 (ns-2.30)
diff -urN ns-2.30-orig/Makefile.in ns-2.30-eu112/Makefile.in
--- ns-2.30-orig/Makefile.in	2006-09-25 08:18:23.000000000 +0307
+++ ns-2.30-eu112/Makefile.in	2006-10-07 22:27:44.000000000 +0307
@@ -52,7 +52,7 @@
 # for diffusion
 #DIFF_INCLUDES = "./diffusion3/main ./diffusion3/lib ./diffusion3/nr ./diffusion3/ns"
 
-CCOPT	= @V_CCOPT@ 
+CCOPT	= -Wall @V_CCOPT@ 
 STATIC	= @V_STATIC@
 #LDFLAGS	= $(STATIC)
 LDFLAGS	= @LDFLAGS@
@@ -307,6 +307,15 @@
 	wpan/p802_15_4nam.o wpan/p802_15_4phy.o \
 	wpan/p802_15_4sscs.o wpan/p802_15_4timer.o \
 	wpan/p802_15_4trace.o wpan/p802_15_4transac.o \
+	umts/am.o umts/classifier-sport.o umts/demuxer.o \
+	umts/demuxerRtModule.o  umts/networkInterface.o \
+	umts/nif-classifier.o  umts/tcs.o umts/um.o \
+	umts/umtslink.o umts/umtstrace.o \
+	umts/hsdpalink.o umts/um-hs.o \
+	umts/umts-timers.o umts/virtual_umtsmac.o \
+	umts/am-hs.o \
+	umts/umts-queue.o umts/dummy_drop_tail.o \
+	umts/error_model.o tools/coot.o \
 	@V_STLOBJ@
 
 
@@ -462,6 +471,7 @@
 	tcl/lib/ns-srcrt.tcl \
 	tcl/mcast/ns-lms.tcl \
 	tcl/lib/ns-qsnode.tcl \
+	tcl/lib/ns-umts.tcl \
 	@V_NS_TCL_LIB_STL@
 
 $(GEN_DIR)ns_tcl.cc: $(NS_TCL_LIB)
diff -urN ns-2.30-orig/common/packet.h ns-2.30-eu112/common/packet.h
--- ns-2.30-orig/common/packet.h	2006-09-25 08:18:04.000000000 +0307
+++ ns-2.30-eu112/common/packet.h	2006-10-07 22:15:37.000000000 +0307
@@ -151,6 +151,20 @@
 	PT_PGM,
 #endif //STL
 
+	// UMTS - used by hdr_cmn class for tracing purpose
+	PT_UM,
+        PT_AMDA,
+        PT_AMPA,
+        PT_AMPBPA,
+        PT_AMBA,
+        PT_AMPBBA,
+	// Used for tracking HARQ transmissions (MAC-hs PDUs)
+	PT_AMDA_H1,
+	PT_AMDA_H2,
+	PT_AMDA_H3,
+	// End UMTS
+
+
 	// LMS packets
 	PT_LMS,
 	PT_LMS_SETUP,
@@ -164,6 +178,9 @@
 	// XCP packet
 	PT_XCP,
 	
+	// COOT packet
+	PT_COOT,
+
 	// HDLC packet
 	PT_HDLC,
 
@@ -249,6 +266,18 @@
 		// for PGM
 		name_[PT_PGM] = "PGM";
 #endif //STL
+		// UMTS 
+		name_[PT_UM] = "UM";
+                name_[PT_AMDA] = "AM_Data";
+                name_[PT_AMPA] = "AM_Pos_Ack";
+                name_[PT_AMPBPA] = "AM_Piggyback_Ack";
+                name_[PT_AMBA] = "AM_Bitmap_ack";
+                name_[PT_AMPBBA] = "AM_Piggyback_Back";
+		// For HARQ transmission tracking
+		name_[PT_AMDA_H1] = "HARQ_1";
+		name_[PT_AMDA_H2] = "HARQ_2";
+		name_[PT_AMDA_H3] = "HARQ_3";
+		// End UMTS
 
 		// LMS entries
 		name_[PT_LMS]="LMS";
@@ -266,6 +295,9 @@
 		// XCP
 		name_[PT_XCP]="xcp";
 
+		// coot
+		name_[PT_COOT]="coot";
+
 		// Bell Labs (PackMime OL)
 		name_[PT_BLTRACE]="BellLabsTrace";
 		
diff -urN ns-2.30-orig/tcl/lib/ns-default.tcl ns-2.30-eu112/tcl/lib/ns-default.tcl
--- ns-2.30-orig/tcl/lib/ns-default.tcl	2006-09-25 08:18:07.000000000 +0307
+++ ns-2.30-eu112/tcl/lib/ns-default.tcl	2006-10-07 22:38:15.000000000 +0307
@@ -96,7 +96,7 @@
 # change DropTail to RED for RED on individual queues
 FQLink set queueManagement_ DropTail
 
-Queue/DropTail set drop_front_ false
+Queue/DropTail set drop_front_ true
 Queue/DropTail set summarystats_ false
 Queue/DropTail set queue_in_bytes_ false
 Queue/DropTail set mean_pktsize_ 500
@@ -475,6 +475,12 @@
 Application/Traffic/Pareto set packetSize_ 210
 Application/Traffic/Pareto set shape_ 1.5
 
+Application/Traffic/Coot set burst_time_ 500ms
+Application/Traffic/Coot set idle_time_ 500ms
+Application/Traffic/Coot set rate_ 64Kb
+Application/Traffic/Coot set packetSize_ 210
+Application/Traffic/Coot set shape_ 1.5
+
 Application/Traffic/RealAudio set burst_time_ 0.05ms
 Application/Traffic/RealAudio set idle_time_ 1800ms
 Application/Traffic/RealAudio set rate_ 2Kb
@@ -662,6 +668,137 @@
 LL set debug_ false
 LL set avoidReordering_ false ;	#not used 
 
+# UMTS starts
+UMTS/RLC/UM set avoidReordering_                      false
+UMTS/RLC/UM set payload_                              40
+UMTS/RLC/UM set bandwidth_                            0
+UMTS/RLC/UM set debug_                                false
+UMTS/RLC/UM set macDA_                                -1
+UMTS/RLC/UM set win_                                  1024
+UMTS/RLC/UM set temp_pdu_timeout_time_                10ms
+UMTS/RLC/UM set buffer_level_max_                     500
+UMTS/RLC/UM set TTI_                                  10ms
+UMTS/RLC/UM set length_indicator_                     7
+UMTS/RLC/UM set min_concat_data_                      3
+UMTS/RLC/UM set delay_                                50us
+
+UMTS/RLC/UMHS set avoidReordering_                      false
+UMTS/RLC/UMHS set debug_                              false
+UMTS/RLC/UMHS set macDA_                              -1
+UMTS/RLC/UMHS set win_                                4095
+UMTS/RLC/UMHS set temp_pdu_timeout_time_              2ms
+UMTS/RLC/UMHS set credit_allocation_interval_         15 
+UMTS/RLC/UMHS set flow_max_                           20 
+UMTS/RLC/UMHS set priority_max_                       5 
+UMTS/RLC/UMHS set buffer_level_max_                   500
+UMTS/RLC/UMHS set payload_                            40
+UMTS/RLC/UMHS set TTI_                                2ms
+UMTS/RLC/UMHS set length_indicator_                   7
+UMTS/RLC/UMHS set min_concat_data_                    3
+UMTS/RLC/UMHS set bandwidth_                          0
+UMTS/RLC/UMHS set delay_                              50us
+
+UMTS/RLC/AM set avoidReordering_                      false
+UMTS/RLC/AM set ack_mode_                             2
+UMTS/RLC/AM set win_                                  1024
+UMTS/RLC/AM set maxRBSize_                            100kbytes
+UMTS/RLC/AM set overhead_                             20us
+UMTS/RLC/AM set payload_                              40
+UMTS/RLC/AM set rtx_timeout_                          140ms
+UMTS/RLC/AM set noFastRetrans_                        0
+UMTS/RLC/AM set numdupacks_                           2
+UMTS/RLC/AM set poll_PDU_                             256
+UMTS/RLC/AM set poll_timeout_                         170ms
+UMTS/RLC/AM set stprob_timeout_                       150ms
+UMTS/RLC/AM set macDA_                                -1
+UMTS/RLC/AM set debug_                                false
+UMTS/RLC/AM set bandwidth_                            0
+UMTS/RLC/AM set TTI_                                  10ms
+UMTS/RLC/AM set length_indicator_                     7
+UMTS/RLC/AM set ack_pdu_header_                       1
+UMTS/RLC/AM set status_pdu_header_                    20
+UMTS/RLC/AM set min_concat_data_                      3
+UMTS/RLC/AM set max_status_delay_                     10ms
+UMTS/RLC/AM set max_ack_delay_                        10ms
+UMTS/RLC/AM set delay_                                50us
+
+UMTS/RLC/AMHS set avoidReordering_                    false
+UMTS/RLC/AMHS set debug_                              false
+UMTS/RLC/AMHS set win_                                4095
+UMTS/RLC/AMHS set temp_pdu_timeout_time_              2ms
+UMTS/RLC/AMHS set credit_allocation_interval_         15
+UMTS/RLC/AMHS set flow_max_                           20 
+UMTS/RLC/AMHS set priority_max_                       5 
+UMTS/RLC/AMHS set buffer_level_max_                   500 
+UMTS/RLC/AMHS set TTI_                                2ms
+UMTS/RLC/AMHS set payload_                            40
+UMTS/RLC/AMHS set poll_PDU_                           256
+UMTS/RLC/AMHS set poll_timeout_                       170ms
+UMTS/RLC/AMHS set stprob_timeout_                     150ms
+UMTS/RLC/AMHS set length_indicator_                   7
+UMTS/RLC/AMHS set status_pdu_header_                  4
+UMTS/RLC/AMHS set min_concat_data_                    3
+UMTS/RLC/AMHS set macDA_                              -1
+UMTS/RLC/AMHS set status_timeout_                     1ms
+UMTS/RLC/AMHS set bandwidth_                          0
+UMTS/RLC/AMHS set delay_                              50us
+
+Phy/Umts set debug_                                   false
+
+Mac/Umts set delay_                                   10us
+Mac/Umts set TTI_                                     10ms
+Mac/Umts set shared_delay_                            3ms
+Mac/Umts set debug_                                   false
+
+Phy/Hsdpa set debug_                                  false
+
+Mac/Hsdpa set delay_                                  10us
+Mac/Hsdpa set TTI_                                    2ms
+Mac/Hsdpa set credit_allocation_interval_             15
+Mac/Hsdpa set debug_                                  false
+Mac/Hsdpa set credit_interval_                        15
+Mac/Hsdpa set flow_control_rtt_                       30ms
+Mac/Hsdpa set flow_max_                               20 
+Mac/Hsdpa set priority_max_                           5 
+Mac/Hsdpa set ack_process_delay_                      4ms 
+Mac/Hsdpa set stall_timer_delay_                      25ms
+Mac/Hsdpa set scheduler_type_                         2 
+Mac/Hsdpa set max_mac_hs_buffer_level_                250
+Mac/Hsdpa set mac_hs_headersize_                      21
+Mac/Hsdpa set flow_control_mode_                      1
+Mac/Hsdpa set nr_harq_rtx_                            3
+Mac/Hsdpa set nr_harq_processes_                      6
+Mac/Hsdpa set reord_buf_size_                         64
+Mac/Hsdpa set alpha_				      0.999
+
+
+UmtsNetworkInterface set debug_                       false
+
+Demuxer set debug_                                    false
+
+Channel set delay_                                    5us
+
+TrChMeasurer set THP_REPORT_INTERVAL_                 500ms
+TrChMeasurer set DOWNSWITCH_THRESHOLD_                8kbps
+TrChMeasurer set DOWNSWITCH_TIMER_THRESHOLD_          16kbps
+TrChMeasurer set DL_RLC_BUF_UPSWITCH_THRESH_sRAB_     500bytes
+TrChMeasurer set UL_RLC_BUF_UPSWITCH_THRESH_sRAB_     265bytes
+TrChMeasurer set PENDING_TIME_AFTER_TRIGGER_          0.5s
+TrChMeasurer set BUFF_CHECK_INTERVAL_                 10ms
+TrChMeasurer set debug_                               false
+
+ChannelSwitcher set DOWNSWITCH_TIMER_sRAB_            1s
+ChannelSwitcher set noSwitching_                      true 
+ChannelSwitcher set debug_                            false
+
+Queue/DummyDropTail set drop_front_                   0
+Queue/DummyDropTail set summarystats_                 0
+Queue/DummyDropTail set queue_in_bytes_               0
+Queue/DummyDropTail set mean_pktsize_                 0
+Queue/DummyDropTail set drop_front_                   0
+
+# UMTS ends
+
 Snoop set debug_ false
 
 #change wrt Mike's code
diff -urN ns-2.30-orig/tcl/lib/ns-lib.tcl ns-2.30-eu112/tcl/lib/ns-lib.tcl
--- ns-2.30-orig/tcl/lib/ns-lib.tcl	2006-09-25 08:18:07.000000000 +0307
+++ ns-2.30-eu112/tcl/lib/ns-lib.tcl	2006-10-07 22:41:25.000000000 +0307
@@ -217,6 +217,9 @@
 #LMS
 source ../mcast/ns-lms.tcl
 
+#UMTS
+source ns-umts.tcl
+
 # STL dependent modules get included
 # ONLY when STL is found
 
diff -urN ns-2.30-orig/tcl/lib/ns-packet.tcl ns-2.30-eu112/tcl/lib/ns-packet.tcl
--- ns-2.30-orig/tcl/lib/ns-packet.tcl	2006-09-25 08:18:07.000000000 +0307
+++ ns-2.30-eu112/tcl/lib/ns-packet.tcl	2006-10-07 22:44:23.000000000 +0307
@@ -165,6 +165,12 @@
 	IMEP 	# Internet MANET Encapsulation Protocol, for ad-hoc networks
         MIP 	# Mobile IP, mobile/mip-reg.cc
 	Smac 	# Sensor-MAC
+	# UMTS - RLC Header is defined in um.h
+	RLC
+	# UMTS - MAC_HS header is defined in hsdpalink.h
+	MAC_HS
+	MPEG4
+	# End UMTS
 	TORA 	# routing protocol for ad-hoc networks
 # Other:
 	Encap 	# common/encap.cc
diff -urN ns-2.30-orig/tcl/lib/ns-umts.tcl ns-2.30-eu112/tcl/lib/ns-umts.tcl
--- ns-2.30-orig/tcl/lib/ns-umts.tcl	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/tcl/lib/ns-umts.tcl	2006-10-07 23:22:00.000000000 +0307
@@ -0,0 +1,1551 @@
+# Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+# Copyright (c) 2005 Twente Institute for Wireless and Mobile
+#		Communications B.V. (WMC)
+# 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 must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the
+#     distribution.
+# 3. Neither the name of Ericsson Telecommunicatie B.V. or WMC may be used
+#     to endorse or promote products derived from this software without
+#     specific prior written permission.
+# 
+# 
+# THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+# CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# 
+# 
+# Contact for feedback on EURANE: eurane@ti-wmc.nl
+# EURANE = Enhanced UMTS Radio Access Network Extensions
+# website: http://www.ti-wmc.nl/eurane/
+#
+# $Id: ns-umts.tcl,v 1.4 2005/10/17 13:28:25 neill Exp $
+#
+#======================================================================
+#
+# Enhanced UMTS:  Extensions for NS-2 (support for HS-DSCH, MAC-hs)
+#
+# ======================================================================
+#
+# Configuration related functions
+#
+# ======================================================================
+
+
+Simulator instproc UmtsNodeType	{val} { $self set UmtsNodeType_  $val }
+Simulator instproc downlinkBW	{val} { $self set downlinkBW_  $val }
+Simulator instproc downlinkTTI	{val} { $self set downlinkTTI_  $val }
+Simulator instproc uplinkBW	{val} { $self set uplinkBW_  $val }
+Simulator instproc uplinkTTI	{val} { $self set uplinkTTI_  $val }
+Simulator instproc baseStation	{val} { $self set baseStation_  $val }
+Simulator instproc radioNetworkController {val} { $self set radioNetworkController_  $val }
+
+#HSDPA additions################################################################
+Simulator instproc hs_downlinkBW	{val} { $self set hs_downlinkBW_  $val }
+Simulator instproc hs_downlinkTTI	{val} { $self set hs_downlinkTTI_  $val }
+Simulator instproc hsdschEnabled	{val} { $self set hsdschEnabled_  $val }
+Simulator instproc hsdsch_rlc_set	{val} { $self set hsdsch_rlc_set_  $val }
+Simulator instproc hs_am {val} { $self set hs_am_  $val }
+Simulator instproc hs_mac {val} { $self set hs_mac_  $val }
+Simulator instproc hs_chan	{val} { $self set hs_chan_  $val }
+################################################################################
+
+
+# ======================================================================
+#
+# IP PDU - RLC PDU Demultiplexer at UmtsNode entry
+#
+# ======================================================================
+
+RtModule/Demuxer instproc register { node } {
+    $self attach-node $node
+    
+    $self instvar classifier_
+    set classifier_ [new Demuxer]
+
+    $node insert-entry-connector $self $classifier_ up-target
+}
+
+
+# ======================================================================
+#
+# The Node/UmtsNode class 
+#
+# ======================================================================
+
+Class Node/UmtsNode -superclass Node
+
+Node/UmtsNode instproc init args {
+    eval $self next $args		;# parent class constructor
+
+    $self instvar nifs_ type_
+    $self instvar bs_ rnc_ Iub_ port_classifier_ nif_classifier_
+    $self instvar chan_tx_ chan_rx_ phy_tx_ phy_rx_ mac_ drophead_ cs_ tcm_ connector_ nif_ ll_ 
+
+    set nifs_	0		;# number of network interfaces
+}
+
+
+
+#
+# - Place the existing classifier entry at slot $hook of the new connector. 
+#
+
+Node/UmtsNode instproc insert-entry-connector { module clsfr hook } {
+
+    $self instvar classifier_ mod_assoc_ hook_assoc_
+
+    set hook_assoc_($clsfr) $classifier_
+
+    if { $hook == "up-target" } {
+	$clsfr up-target $classifier_
+    } elseif { $hook == "down-target" } {
+	$clsfr down-target $classifier_
+    } else {
+	puts "Error: wrong value of hook; exiting"
+	exit 1
+    }
+
+    # Associate this module to the classifier, so if the classifier is
+    # removed later, we'll remove the module as well.
+    set mod_assoc_($clsfr) $module
+    set classifier_ $clsfr
+}
+
+
+#
+# Attach an agent to a node.  Pick a port and
+# bind the agent to the port number.
+# if portnumber is 255, default target is set to the routing agent
+#
+
+Node/UmtsNode instproc add-target {agent port } {
+
+    $self instvar dmux_ address_
+    
+    if { $dmux_ == "" } {
+	# Use the default mask_ and port_ values
+	set dmux_ [new Classifier/Port]
+	# point the node's routing entry to itself
+	# at the port demuxer (if there is one)
+	$self add-route $address_ $dmux_
+    }
+    
+    if { $port == [Node set rtagent_port_] } {
+	# Set the default target at C++ level.  
+	set tmp [$self set classifier_]
+	[$tmp up-target] defaulttarget $agent
+	$dmux_ install $port $agent
+    } else {
+	# Send Target
+	$agent target [$self entry]
+
+	# Recv Target
+	$dmux_ install $port $agent
+    }
+}
+
+
+# ======================================================================
+#
+# methods for creating UmtsNodes
+#
+# ======================================================================
+
+Simulator instproc create-Umtsnode {} {
+
+    $self instvar UmtsNodeType_
+    $self instvar radioNetworkController_ baseStation_
+    $self instvar downlinkBW_ uplinkBW_ downlinkTTI_ uplinkTTI_
+    #HSDPA addition######################################################
+    $self instvar hsdschEnabled_ hs_downlinkBW_ hs_downlinkTTI_
+    $self instvar hsdsch_rlc_set_ hsdsch_rlc_nif_
+    #####################################################################
+    
+    if {![info exists UmtsNodeType_]} {
+	puts "Error: create-Umtsnode called, but no UmtsNodeType_; exiting"
+	exit 1
+    }
+    
+    # Case conversion (for compatibility)
+    if {$UmtsNodeType_ == "BS"} {set UmtsNodeType_ "bs"}
+    if {$UmtsNodeType_ == "UE"} {set UmtsNodeType_ "ue"}
+    if {$UmtsNodeType_ == "RNC"} {set UmtsNodeType_ "rnc"}
+    if {[lsearch {bs ue rnc} $UmtsNodeType_] < 0} {
+	puts "Error: undefined UmtsNodeType: $UmtsNodeType_; exiting"
+	exit 1
+    }
+    
+    if {$UmtsNodeType_ == "ue" } {
+	if {![info exists baseStation_] || ![info exists radioNetworkController_]} {
+	    puts "Error: Failed to set BS and RNC for UE; exiting"
+	    exit 1
+	}
+    }
+    if {$UmtsNodeType_ == "ue" || $UmtsNodeType_ == "bs"} {
+	if {![info exists downlinkBW_] || ![info exists uplinkBW_]} {
+	    puts "Error: Failed to set uplink and downlink RLC data rate. exiting"
+	    exit 1
+	}
+	if {![info exists downlinkTTI_] || ![info exists uplinkTTI_]} {
+	    puts "Error: Failed to set uplink and downlink TTI. exiting"
+	    exit 1
+	}
+    }
+    
+    # Create the Umtsnode
+    set tmp [$self newUmtsnode]
+    return $tmp
+}
+
+
+Simulator instproc newUmtsnode {} {
+
+    $self instvar UmtsNodeType_ baseStation_ radioNetworkController_ 
+    $self instvar downlinkBW_ uplinkBW_ downlinkTTI_ uplinkTTI_ Node_ link_
+    #HSDPA addition######################################################
+    $self instvar hsdschEnabled_ hs_downlinkBW_ hs_downlinkTTI_
+    $self instvar hsdsch_rlc_set_ hsdsch_rlc_nif_
+    #####################################################################
+    
+    if ![info exists UmtsNodeType_] {
+	puts "Error: UmtsNodeType_ does not exist in newUmtsnode; exiting"
+	exit 1
+    }
+
+    set node [new Node/UmtsNode]
+    
+    $node set type_ $UmtsNodeType_
+    $node register-module [new RtModule/Demuxer]
+    
+    if {$UmtsNodeType_ == "ue"} {
+	$node instvar bs_ rnc_ classifier_ port_classifier_ nif_classifier_ mac_ id_
+	set bs_ $baseStation_
+	set rnc_ $radioNetworkController_
+	set port_classifier_ [new Classifier/SrcPort]
+	set nif_classifier_ [new Classifier/Nif]
+	$node add-target $port_classifier_ 255
+	$classifier_ down-target $nif_classifier_
+	$node setup-common rach $uplinkBW_ $uplinkTTI_ [$bs_ set chan_rx_(0)]
+	$node setup-common fach [$bs_ set chan_tx_(1)]
+   
+   # set MAC source address (for RLC) to FACH NIF identifier
+   $mac_(1) SA $id_
+	
+	#################################################################
+	$rnc_ add-dest-classifier [$node set address_]
+
+	# Set up- and downlinks from UE and BS??
+	set link_([$node id]:[$bs_ id]) [new Link $node $bs_]
+	$link_([$node id]:[$bs_ id]) set queue_ [new Queue/DropTail]
+	set link_([$bs_ id]:[$node id]) [new Link $bs_ $node]
+	$link_([$bs_ id]:[$node id]) set queue_ [new Queue/DropTail]
+
+   }
+    
+    if {$UmtsNodeType_ == "bs"} {
+	$node instvar classifier_ nif_classifier_ mac_ id_
+	set nif_classifier_ [new Classifier/Nif]
+	$classifier_ down-target $nif_classifier_
+	$node setup-common rach
+	$node setup-common fach $downlinkBW_ $downlinkTTI_
+	
+	$mac_(0) SA $id_
+	
+	
+    }
+
+    if {$UmtsNodeType_ == "rnc"} {
+	$node instvar classifier_ nif_classifier_
+	set nif_classifier_ [new Classifier/Nif]
+	$classifier_ down-target $nif_classifier_
+    }
+    
+    set Node_([$node id]) $node
+    $node set ns_ $self
+    $self check-node-num
+    return $node
+}
+
+
+Node/UmtsNode instproc add-dest-classifier { address } {
+
+    $self instvar type_ classifier_ port_classifier_
+    if {$type_ == "rnc"} {
+	set port_classifier_($address) [new Classifier/Port]
+	[$classifier_ up-target] install $address $port_classifier_($address)
+    } 
+}
+
+Node/UmtsNode instproc add-gateway { node } {
+    $self instvar type_ classifier_ 
+    [Simulator instance] instvar link_
+    
+    if {$type_ == "rnc"} {
+	set link $link_([$self id]:[$node id])
+	[$classifier_ up-target] defaulttarget [$link head]
+    } else {
+	puts "Error."
+	puts "Correct Syntax is : $RNC add-gateway $Gateway"
+    }
+    
+}
+
+# This is quite dirty: It passes the method from the node to the second
+# MAC, which should be the Mac-hs.
+
+Node/UmtsNode instproc setErrorTrace { flow filename } {
+   $self instvar mac_
+
+   #TODO: add checks whether it is really a BS with HSDPA enabled.
+   $mac_(2) setErrorTrace $flow $filename
+}
+
+Node/UmtsNode instproc loadSnrBlerMatrix { filename } {
+   $self instvar mac_
+
+   #TODO: add checks whether it is really a BS with HSDPA enabled.
+   $mac_(2) loadSnrBlerMatrix $filename
+}
+
+# ======================================================================
+#
+# methods for creating Umts channels, and error models
+#
+# ======================================================================
+
+Simulator instproc setup-Iub { bs rnc ubw dbw udelay ddelay type args } {
+
+    $self instvar link_ traceAllFile_ traceAllFileBackup_
+
+    set i1 [$bs id]
+    set i2 [$rnc id]
+
+    if [info exists traceAllFile_] {
+	set traceAllFileBackup_ $traceAllFile_
+	set traceAllFile_ ""
+    }
+
+    eval $self simplex-link $bs $rnc $ubw $udelay $type
+    eval $self simplex-link $rnc $bs $dbw $ddelay $type
+
+    if [info exists traceAllFileBackup_] {
+	set traceAllFile_ $traceAllFileBackup_
+	set traceAllFileBackup_ ""
+	$self trace-rlc-queue $bs $rnc $traceAllFile_
+	$self trace-rlc-queue $rnc $bs $traceAllFile_
+    }
+
+    $bs set Iub_ $link_($i1:$i2)
+    $rnc set Iub_ $link_($i2:$i1)
+    
+    $bs update-Iub-path
+    $rnc update-Iub-path
+}
+
+
+Node/UmtsNode instproc update-Iub-path {} {
+
+    $self instvar type_ nifs_ nif_ mac_ Iub_
+
+    if {$type_ == "bs"} {
+	set head [$Iub_ set head_]
+
+	for {set i 0} {$i < $nifs_} {incr i} {
+	    if {$i != 1 && [info exists mac_($i)]} {
+		$mac_($i) up-target $head 
+	    }
+	}
+    } elseif {$type_ == "rnc"} {
+
+	set head [$Iub_ set head_]
+
+	for {set i 0} {$i < $nifs_} {incr i} {
+	    if {[info exists nif_($i)]} {
+		$nif_($i) target $head
+	    }
+	}
+	
+    } 
+}
+
+
+Simulator instproc create-dch { node l_agent } {
+
+    $self instvar llType_ downlinkBW_ uplinkBW_ downlinkTTI_ uplinkTTI_
+
+    set inchan [new Channel]
+    set outchan [new Channel]
+    set cs [new ChannelSwitcher]
+    
+    set bs [$node set bs_]
+    set rnc [$node set rnc_]
+
+    set n_tti [[$node set mac_(0)] TTI]
+    set n_bw [[$node set mac_(0)] BW]
+    
+    set b_tti [[$bs set mac_(1)] TTI]
+    set b_bw [[$bs set mac_(1)] BW]
+    
+    $cs rlc_DS_info $n_tti $n_bw $b_tti $b_bw
+
+    set nifs1 [eval $rnc add-interface dch $llType_ $downlinkTTI_ $downlinkBW_]
+    set ll [$rnc set ll_($nifs1)]
+    set nifs2 [eval $bs add-interface dch $llType_ $downlinkTTI_ $downlinkBW_ $inchan $outchan $cs $ll]
+    set nifs3 [eval $node add-interface dch $llType_ $uplinkTTI_ $uplinkBW_ $outchan $inchan $cs]
+    
+    set n_tti [[$node set mac_($nifs3)] TTI]
+    set n_bw [[$node set mac_($nifs3)] BW]
+    
+    set b_tti [[$bs set mac_($nifs2)] TTI]
+    set b_bw [[$bs set mac_($nifs2)] BW]
+
+    $cs rlc_US_info $n_tti $n_bw $b_tti $b_bw
+
+    [$node set nif_($nifs3)] label $nifs1
+    [$rnc set nif_($nifs1)] label $nifs1
+    
+    [$node set ll_($nifs3)] addr [$node id]
+    [$node set ll_($nifs3)] daddr [$rnc id]
+    
+    [$rnc set ll_($nifs1)] addr [$rnc id]
+    [$rnc set ll_($nifs1)] daddr [$node id]
+
+    [$node set ll_($nifs3)] macDA [$bs id]]
+    [$rnc set ll_($nifs1)] macDA [$node id]
+
+[$node set mac_($nifs3)] SA [$node id]
+[$bs set mac_($nifs2)] SA [$bs id]
+
+$rnc set-nif-classifier $nifs1 $nifs1
+$bs set-nif-classifier $nifs1 $nifs2
+$node set-nif-classifier $nifs1 $nifs3
+
+$node set-port-path [$l_agent port] $nifs3
+$rnc set-port-path [$l_agent port] $nifs1 [$node set address_]
+
+$bs update-Iub-path
+$rnc update-Iub-path
+
+return $nifs3
+}
+
+
+Simulator instproc attach-dch { node l_agent nifs } {
+
+    $node instvar chan_tx_ chan_rx_ id_
+
+    if { ![info exists chan_tx_($nifs)] || ![info exists chan_rx_($nifs)] } {
+	puts "Invalid DCH stack given for Node ID:$id_"
+	exit 1
+
+    } else {
+	set bs [$node set bs_]
+	set rnc [$node set rnc_]
+
+	$node set-port-path [$l_agent port] $nifs
+	set nifs1 [[$node set nif_($nifs)] label]
+	$rnc set-port-path [$l_agent port] $nifs1 [$node set address_]
+    }
+}
+
+Simulator instproc create-hsdsch { node l_agent} {
+
+   # TODO: check whether this method has been called before (ie: check whether
+   # hs_am, hs_mac and hs_chan are initialized)
+
+   $self instvar llType_ hsdschEnabled_ hsdsch_rlc_set_ hsdsch_rlc_nif_
+#   $self instvar hs_downlinkTTI_ hs_downlinkBW_ uplinkTTI_ uplinkBW_
+   $self instvar hs_downlinkTTI_ hs_downlinkBW_
+   $self instvar hs_am hs_mac hs_chan
+
+   set hs_chan [new Channel]
+
+   set bs [$node set bs_]
+   set rnc [$node set rnc_]
+   if {$llType_ == "UMTS/RLC/AM"} {
+      set hs_am [eval $rnc add-interface hsdsch UMTS/RLC/AMHS $hs_downlinkTTI_ $hs_downlinkBW_]
+   } else {
+      set hs_am [eval $rnc add-interface hsdsch UMTS/RLC/UMHS $hs_downlinkTTI_ $hs_downlinkBW_]
+   }
+   set hs_mac [eval $bs add-interface hsdsch $llType_ $hs_downlinkTTI_ $hs_downlinkBW_ $hs_chan]
+
+   set tmp [$self attach-hsdsch $node $l_agent]
+   return tmp
+}
+
+Simulator instproc attach-hsdsch { node l_agent} {
+
+   # TODO: check whether create-hsdsch has been called before this method
+
+   $self instvar llType_ hsdschEnabled_ hsdsch_rlc_set_ hsdsch_rlc_nif_
+   $self instvar hs_downlinkTTI_ hs_downlinkBW_ uplinkTTI_ uplinkBW_
+   $self instvar hs_am hs_mac hs_chan
+
+   set bs [$node set bs_]
+   set rnc [$node set rnc_]
+
+   set hs_ue [eval $node add-interface hsdsch $llType_ $uplinkTTI_ $uplinkBW_ $hs_chan]
+
+   [$node set nif_($hs_ue)] label $hs_am
+   [$node set nif_([expr $hs_ue + 1])] label $hs_am
+   [$rnc set nif_($hs_am)] label $hs_am
+
+   [$node set ll_($hs_ue)] addr [$node id]
+   [$node set ll_($hs_ue)] daddr [$rnc id]
+
+   [$rnc set ll_($hs_am)] addr [$rnc id]
+   [$rnc set ll_($hs_am)] daddr [$node id]
+
+   [$node set ll_($hs_ue)] macDA [$bs id]]
+   [$rnc set ll_($hs_am)] macDA [$node id]
+
+   [$node set mac_($hs_ue)] SA [$node id]
+   [$node set mac_([expr $hs_ue + 1])] SA [$node id]
+   [$bs set mac_($hs_mac)] SA [$bs id]
+   [$bs set mac_([expr [$node id] + 1])] SA [$bs id]
+
+   $rnc set-nif-classifier $hs_am $hs_am
+   $bs set-nif-classifier $hs_am $hs_mac
+   $node set-nif-classifier $hs_am $hs_ue
+
+
+   $node set-port-path [$l_agent port] $hs_ue
+   $rnc set-port-path [$l_agent port] $hs_am [$node set address_]
+
+#   $node set-port-path 0 $hs_ue
+#   $rnc set-port-path 0 $hs_am [$node set address_]
+
+   $bs update-Iub-path
+   $rnc update-Iub-path
+
+   # now create the uplink
+
+
+
+return $hs_ue
+
+
+
+}
+
+Simulator instproc attach-common { node l_agent} {
+
+    $self instvar llType_ hsdschEnabled_
+
+    set bs [$node set bs_]
+    set rnc [$node set rnc_]
+
+    set n_tti [[$node set mac_(0)] TTI]
+    set n_bw [[$node set mac_(0)] BW]
+
+    set b_tti [[$bs set mac_(1)] TTI]
+    set b_bw [[$bs set mac_(1)] BW] 
+    
+
+    set nifs1 [eval $rnc add-interface common $llType_ $b_tti $b_bw]
+    set nifs3 [eval $node add-interface common $llType_ $n_tti $n_bw]
+
+    [$node set nif_($nifs3)] label $nifs1
+    [$rnc set nif_($nifs1)] label $nifs1
+
+    [$node set ll_($nifs3)] addr [$node id]
+    [$node set ll_($nifs3)] daddr [$rnc id]
+    
+    [$rnc set ll_($nifs1)] addr [$rnc id]
+    [$rnc set ll_($nifs1)] daddr [$node id]
+    
+    [$node set ll_($nifs3)] macDA [$bs id]
+    [$rnc set ll_($nifs1)] macDA [$node id]
+    
+    $rnc set-nif-classifier $nifs1 $nifs1
+    
+    
+    $bs set-nif-classifier $nifs1 1
+  
+    #########################################
+    
+    $node set-nif-classifier $nifs1 $nifs3
+
+    $node set-port-path [$l_agent port] $nifs3
+    $rnc set-port-path [$l_agent port] $nifs1 [$node set address_]
+
+    $bs update-Iub-path
+    $rnc update-Iub-path
+}
+
+
+
+Node/UmtsNode instproc set-nif-classifier {nif_value stack} {
+
+    $self instvar nif_classifier_ tcm_ connector_ ll_ type_
+
+   if {$type_ == "ue" || $type_ == "rnc"} {
+      $nif_classifier_ install $nif_value $ll_($stack)
+   } elseif {$type_ == "bs"} {
+      if {[info exists connector_($stack)]} {
+         $nif_classifier_ install $nif_value $connector_($stack)
+      } else {
+         $nif_classifier_ install $nif_value $tcm_($stack)
+      }
+   }
+}
+
+
+Node/UmtsNode instproc set-port-path {port nif {address 0}} {
+
+    $self instvar port_classifier_ ll_ type_
+
+    if {$type_ == "ue" } {
+         $port_classifier_ install $port $ll_($nif)
+    } elseif {$type_ == "rnc"} {
+         $port_classifier_($address) install $port $ll_($nif)
+    }
+}
+
+
+
+#============================================================================
+#
+#  The following sets up link layer, mac layer and physical layer structures
+#  etc for the Umts nodes.
+#
+#============================================================================
+
+Node/UmtsNode instproc add-interface args {
+   $self instvar bs_ nifs_ chan_rx_ chan_tx_ phy_rx_ phy_tx_ mac_
+   $self instvar drophead_ cs_ tcm_ connector_ nif_ ll_ type_
+   [Simulator instance]  instvar llType_
+
+   set t $nifs_
+   incr nifs_
+   set linktype [lindex $args 0]
+
+   if {$type_ == "bs"} {
+      if {$linktype == "dch"} {
+
+         set tcm_($t)      [new TrChMeasurer]
+         set drophead_($t) [new Connector]   ;# drop target for mac queue
+         set mac_($t)      [new Mac/Umts]    ;# mac layer
+         set mac_tti       [lindex $args 2]
+         set mac_bw        [lindex $args 3]
+         set phy_tx_($t)   [new Phy/Umts]    ;# interface
+         set phy_rx_($t)   [new Phy/Umts]    ;# interface
+         set chan_rx_($t)  [lindex $args 4]
+         set chan_tx_($t)  [lindex $args 5]
+         set cs_($t)       [lindex $args 6]
+         set ll            [lindex $args 7]
+
+
+         #
+         # Local Variables
+         #
+
+         set tcm $tcm_($t)
+         set cs $cs_($t)
+         set drophead $drophead_($t)
+         set mac $mac_($t)
+         set phy_rx $phy_rx_($t)
+         set phy_tx $phy_tx_($t)
+         set inchan $chan_rx_($t)
+         set outchan $chan_tx_($t)
+
+         #
+         # Stack Head
+         #
+
+
+         $tcm up-target $mac
+         $tcm down-target $mac_(1)
+         $tcm CS $cs
+         $tcm BS 1
+
+	 if {$llType_ == "UMTS/RLC/AM"} {
+         $tcm RLC-AM $ll
+	 $cs downlink-AM $ll
+         } else {
+	 $tcm RLC-UM $ll
+	 $cs downlink-UM $ll
+         }
+ 	 
+         $cs downlink-tcm $tcm
+
+
+         #
+         # Mac Layer
+         #
+         $drophead target [[Simulator instance] set nullAgent_]
+         $mac drop-target $drophead
+
+         $mac down-target $phy_tx
+         $mac set bandwidth_ $mac_bw;
+         $mac set TTI_ $mac_tti;
+         $mac start_TTI
+
+         #
+         # Physical Layer
+         #
+
+         $phy_tx node $self         ;# Bind node <---> interface
+         $phy_tx channel $outchan
+         $phy_rx node $self         ;# Bind node <---> interface
+         $phy_rx up-target $mac
+         $inchan addif $phy_rx      ;# Add to list of Phys receiving on the channel
+
+      } elseif {$linktype == "hsdsch" } {
+         # nodetype bs + hsdsch
+         if {$t>2} {
+   #ifdef TCL_DEBUG
+   #         puts -nonewline "add-interface: t>2: t == "
+   #         puts -nonewline $t
+   #         puts " (t == nifs_ -1)"
+   #endif
+            set connector_($t)   [new Connector]
+            set nif_($t)         [new UmtsNetworkInterface]
+            set drophead_($t)    [new Connector]      ;# drop target for queue
+            set mac_($t)         [new Mac/Umts]       ;# mac layer
+            set mac_tti          [lindex $args 2]     ;# interface queue
+            set mac_bw           [lindex $args 3]
+            set phy_rx_($t)      [new Phy/Umts]       ;# interface
+            set chan_rx_($t)     [lindex $args 4]
+
+
+            #
+            # Local Variables
+            #
+            set connector $connector_($t)
+            set nif $nif_($t)
+            set drophead $drophead_($t)
+            set mac $mac_($t)
+            set phy_rx $phy_rx_($t)
+            set inchan $chan_rx_($t)
+
+            $drophead target [[Simulator instance] set nullAgent_]
+            $mac drop-target $drophead
+
+            #$mac up-target $nif
+            $mac set bandwidth_ $mac_bw;
+            $mac set TTI_ $mac_tti;
+            $mac start_TTI
+
+            $phy_rx node $self         ;# Bind node <---> interface
+            $phy_rx up-target $mac
+            $inchan addif $phy_rx      ;# Add to list of Phys receiving on the channel
+
+         } else {
+         # nodetype bs + hsdsch && t <= 2
+            set connector_($t)   [new Connector]
+            set drophead_($t)    [new Connector]      ;# drop target for mac queue
+            set mac_($t)         [new Mac/Hsdpa]      ;# mac layer
+            set mac_tti          [lindex $args 2]
+            set mac_bw           [lindex $args 3]
+            set phy_tx_($t)      [new Phy/Hsdpa]      ;# interface
+            set chan_tx_($t)     [lindex $args 4]
+
+
+            #
+            # Local Variables
+            #
+
+            set connector $connector_($t)
+            #set tcm $tcm_($t)
+            #set cs $cs_($t)
+            set drophead $drophead_($t)
+            set mac $mac_($t)
+            set phy_tx $phy_tx_($t)
+            set outchan $chan_tx_($t)
+
+            #
+            # Stack Head
+            #
+
+            #$tcm up-target $mac
+            #$tcm down-target $mac_(1)
+            #$tcm CS $cs
+            #$tcm BS 1
+            #$tcm RLC-AM $ll
+
+            #$cs downlink-AM $ll
+            #$cs downlink-tcm $tcm
+
+            $connector target $mac
+
+            #
+            # Mac Layer
+            #
+            $drophead target [[Simulator instance] set nullAgent_]
+            $mac drop-target $drophead
+
+            $mac down-target $phy_tx
+            $mac set bandwidth_ $mac_bw;
+            $mac set TTI_ $mac_tti;
+            $mac start_TTI
+            $mac start_sched
+
+            #
+            # Physical Layer
+            #
+
+            $phy_tx node $self      ;# Bind node <---> interface
+            $phy_tx channel $outchan
+         }
+      }
+
+   } elseif {$type_ == "rnc" } {
+      if {$linktype == "hsdsch"} {
+
+            ## RNC LL setup for 'hsdsch' channel
+
+            set ll_($t) [new [lindex $args 1]]     ;# link layer
+
+            #
+            # Local Variables
+            #
+            set ll $ll_($t)
+
+            #
+            # Link Layer
+            #
+
+            $ll set TTI_ [lindex $args 2];
+            $ll set bandwidth_ [lindex $args 3];
+            $ll start_TTI
+
+
+
+            $ll up-target [$self entry]
+            set nif_($t) [new UmtsNetworkInterface]
+            $ll down-target $nif_($t)
+      } else {
+         # nodetype rnc + hsdsch
+
+         ## RNC LL setup for normal 'common' channels
+
+         set ll_($t) [new [lindex $args 1]]     ;# link layer
+
+         #
+         # Local Variables
+         #
+         set ll $ll_($t)
+
+         #
+         # Link Layer
+         #
+
+         $ll set TTI_ [lindex $args 2];
+         $ll set bandwidth_ [lindex $args 3];
+         $ll start_TTI
+
+
+
+         $ll up-target  [$self entry]
+         set nif_($t)   [new UmtsNetworkInterface]
+         $ll down-target $nif_($t)
+      }
+   } elseif {$type_ == "ue"} {
+      if {$linktype == "common"} {
+         set ll_($t)    [new [lindex $args 1]]        ;# link layer
+         set nif_($t)   [new UmtsNetworkInterface]
+
+         #
+         # Local Variables
+         #
+         set ll $ll_($t)
+         set nif $nif_($t)
+
+         #
+         # Link Layer
+         #
+
+         $ll set TTI_ [lindex $args 2];
+         $ll set bandwidth_ [lindex $args 3];
+         $ll start_TTI
+
+
+         $ll down-target $nif
+         $ll up-target [$self entry]
+
+         #
+         # NetworkInterface
+         #
+
+         $nif target $connector_(0)
+
+      } elseif {$linktype == "dch"} {
+         # UE + dch
+         set ll_($t)       [new [lindex $args 1]]     ;# link layer
+         set nif_($t)      [new UmtsNetworkInterface]
+         set tcm_($t)      [new TrChMeasurer]
+         set mac_tti       [lindex $args 2]           ;# interface queue
+         set drophead_($t) [new Connector]            ;# drop target for queue
+         set mac_($t)      [new Mac/Umts]             ;# mac layer
+         set mac_bw        [lindex $args 3]
+         set phy_tx_($t)   [new Phy/Umts]             ;# interface
+         set phy_rx_($t)   [new Phy/Umts]             ;# interface
+         set chan_rx_($t)  [lindex $args 4]
+         set chan_tx_($t)  [lindex $args 5]
+         set cs_($t)       [lindex $args 6]
+
+         #
+         # Local Variables
+         #
+         set ll $ll_($t)
+         set nif $nif_($t)
+         set tcm $tcm_($t)
+         set cs $cs_($t)
+         set drophead $drophead_($t)
+         set mac $mac_($t)
+         set phy_rx $phy_rx_($t)
+         set phy_tx $phy_tx_($t)
+         set inchan $chan_rx_($t)
+         set outchan $chan_tx_($t)
+
+         #
+         # Link Layer
+         #
+
+         $ll set TTI_ $mac_tti;
+         $ll set bandwidth_ $mac_bw;
+         $ll start_TTI
+
+
+         $ll down-target $nif
+         $ll up-target [$self entry]
+
+         #
+         # NetworkInterface
+         #
+
+         $nif target $tcm
+         #$nif target $connector
+         #
+         # Stack Head
+         #
+
+         $tcm up-target $mac
+         $tcm down-target $mac_(0)
+         $tcm CS $cs
+
+	 if {$llType_ == "UMTS/RLC/AM"} {
+	     $tcm RLC-AM $ll
+	     $cs uplink-AM $ll
+	    } else {
+	     $tcm RLC-UM $ll
+	     $cs uplink-UM $ll
+	 }
+
+
+         $cs uplink-tcm $tcm
+
+
+         #
+         # Mac Layer
+         #
+
+         $drophead target [[Simulator instance] set nullAgent_]
+         $mac drop-target $drophead
+
+         $mac down-target  $phy_tx
+         $mac up-target    $ll
+         $mac set bandwidth_  $mac_bw;
+         $mac set TTI_        $mac_tti;
+         $mac start_TTI
+
+         #
+         # Physical Layer
+         #
+
+         $phy_tx node $self      ;# Bind node <---> interface
+         $phy_rx node $self      ;# Bind node <---> interface
+         $phy_tx channel $outchan
+         $phy_rx up-target $mac
+         $inchan addif $phy_rx   ;# Add to list of Phys receiving on the channel
+      } elseif {$linktype == "hsdsch"} {
+         # UE + hsdsch
+
+         set connector_($t)   [new Connector]
+         set ll_($t)          [new [lindex $args 1]]		;# link layer
+         set nif_($t)         [new UmtsNetworkInterface]
+         set mac_tti          [lindex $args 2]		;# interface queue
+         set drophead_($t)    [new Connector]			;# drop target for queue
+         set mac_($t)         [new Mac/Hsdpa]			;# mac layer
+         set mac_bw           [lindex $args 3]
+         set phy_rx_($t)      [new Phy/Hsdpa]			;# interface
+         set chan_rx_($t)     [lindex $args 4]
+
+
+         #
+         # Local Variables
+         #
+         set connector $connector_($t)
+         set ll $ll_($t)
+         set nif $nif_($t) ;# This nif is only created in order to have 2 elements
+                           # in the array nif_
+         set drophead $drophead_($t)
+         set mac $mac_($t)
+         set phy_rx $phy_rx_($t)
+         set inchan $chan_rx_($t)
+
+         incr nifs_
+         incr t
+
+         set nif_($t) [new UmtsNetworkInterface]
+         set drophead_($t) [new Connector]
+         set mac_($t) [new Mac/Umts]
+         set mac_tti [lindex $args 2]
+         set mac_bw [lindex $args 3]
+         set phy_tx_($t) [new Phy/Umts]
+         set chan_tx_($t) [new Channel]
+         set connector_($t) [new Connector]
+
+         set connector2 $connector_($t)
+         set nif2 $nif_($t)
+         set drophead2 $drophead_($t)
+         set mac2 $mac_($t)
+         set phy_tx $phy_tx_($t)
+         set outchan $chan_tx_($t)
+
+         #
+         # Link Layer
+         #
+
+         $ll set TTI_ $mac_tti;
+         $ll set bandwidth_ $mac_bw;
+         $ll start_TTI
+
+
+         $ll down-target $nif2
+         #$ll down-target $mac2
+         $ll up-target [$self entry]
+
+         #
+         # NetworkInterface
+         #
+
+         $nif2 target $connector2
+         $connector2 target $mac2
+
+         #
+         # Mac Layer
+         #
+
+         $drophead target [[Simulator instance] set nullAgent_]
+         $mac drop-target $drophead
+         $drophead2 target [[Simulator instance] set nullAgent_]
+         $mac2 drop-target $drophead2
+
+         $mac up-target $ll
+         $mac set bandwidth_ $mac_bw;
+         $mac set TTI_ $mac_tti;
+         $mac start_TTI
+
+         $mac2 down-target $phy_tx
+         $mac2 set bandwidth_ $mac_bw;
+         $mac2 set TTI_ $mac_tti;
+         $mac2 start_TTI
+
+         #
+         # Physical Layer
+         #
+         $phy_rx node $self		;# Bind node <---> interface
+         $phy_rx up-target $mac
+         $inchan addif $phy_rx		;# Add to list of Phys receiving on the channel
+
+         $phy_tx node $self		;# Bind node <---> interface
+         $phy_tx channel $outchan
+
+         $bs_ add-interface hsdsch UMTS/RLC/AM [lindex $args 2] [lindex $args 3] $outchan
+
+         set t [expr $t - 1]
+
+      }
+
+
+   } else {
+      #unknown node type
+
+   }
+   return $t
+}
+
+
+
+Node/UmtsNode instproc setup-common args {
+    $self instvar nifs_ chan_rx_ chan_tx_ phy_rx_ phy_tx_ mac_ drophead_ connector_ nif_ ll_ type_
+
+    set linktype [lindex $args 0]
+
+    if {$type_ == "ue"} {
+	set t $nifs_
+	incr nifs_
+
+	if {$linktype == "rach"} {
+	    set connector_($t)	[new Connector]
+	    set drophead_($t) 	[new Connector]			;# drop target for queue
+	    set mac_($t)	[new Mac/Umts]			;# mac layer
+	    set mac_bw		[lindex $args 1]
+	    set mac_tti		[lindex $args 2]
+	    set phy_tx_($t)	[new Phy/Umts]			;# interface
+	    set chan_tx_($t)	[lindex $args 3]
+
+	    #
+	    # Local Variables
+	    #
+
+	    set connector $connector_($t)
+	    set drophead $drophead_($t)
+	    set mac $mac_($t)
+	    set phy_tx $phy_tx_($t)
+	    set outchan $chan_tx_($t)
+
+	    #
+	    # Stack Head
+	    #
+	    
+	    $connector target $mac
+
+	    
+	    #
+	    # Mac Layer
+	    #
+	    
+	    $drophead target [[Simulator instance] set nullAgent_]
+	    $mac drop-target $drophead
+
+	    $mac down-target $phy_tx
+	    $mac set bandwidth_ $mac_bw; 
+	    $mac set TTI_ $mac_tti; 
+	    $mac start_TTI
+	    $mac set_access_delay
+
+	    #
+	    # Physical Layer
+	    #
+	    
+	    $phy_tx node $self		;# Bind node <---> interface
+	    $phy_tx channel $outchan
+
+	} elseif {$linktype == "fach"} {
+	   
+	    set mac_($t)	[new Mac/Umts]		;# mac layer
+	    set phy_rx_($t)	[new Phy/Umts]		;# interface
+	    set chan_rx_($t)	[lindex $args 1]
+	    
+	    #
+	    # Local Variables
+	    #
+       
+	    set mac $mac_($t)
+	    set phy_rx $phy_rx_($t)
+	    set inchan $chan_rx_($t)		
+	    
+	    #
+	    # Mac Layer
+	    #
+	    
+	    $mac up-target [$self entry]			
+
+	    #
+	    # Physical Layer
+	    #
+	    
+	    $phy_rx node $self	;# Bind node <---> interface
+	    $phy_rx up-target $mac
+	    $inchan addif $phy_rx	;# Add to list of Phys receiving on the channel
+
+	}
+	
+    } elseif {$type_ == "bs"} {
+	set t $nifs_
+	incr nifs_
+	
+	if {$linktype == "rach"} {
+	    
+	    set mac_($t)	[new Mac/Umts]		;# mac layer
+	    set phy_rx_($t)	[new Phy/Umts]		;# interface
+	    set chan_rx_($t)	[new Channel]
+
+	    #
+	    # Local Variables
+	    #
+
+	    set mac $mac_($t)
+	    set phy_rx $phy_rx_($t)
+	    set inchan $chan_rx_($t)
+
+
+	    #
+	    # Physical Layer
+	    #
+
+	    $phy_rx node $self		;# Bind node <---> interface
+	    $phy_rx up-target $mac
+	    $inchan addif $phy_rx	;# Add to list of Phys receiving on the channel
+	    
+	} elseif {$linktype == "fach"} {
+	    
+	    set connector_($t)	[new Connector]
+	    set drophead_($t) 	[new Connector]			;# drop target for queue
+	    set mac_($t)	[new Mac/Umts]			;# mac layer
+	    set mac_bw		[lindex $args 1]
+	    set mac_tti		[lindex $args 2]		;# interface queue
+	    set phy_tx_($t)	[new Phy/Umts]			;# interface
+	    set chan_tx_($t)	[new Channel]
+
+	    #
+	    # Local Variables
+	    #
+
+	    set connector $connector_($t)
+	    set drophead $drophead_($t)
+	    set mac $mac_($t)
+	    set phy_tx $phy_tx_($t)
+	    set outchan $chan_tx_($t)
+
+	    #
+	    # Stack Head
+	    #
+	    
+	    $connector target $mac
+
+
+	    #
+	    # Mac Layer
+	    #
+	    
+	    $drophead target [[Simulator instance] set nullAgent_]
+	    $mac drop-target $drophead
+
+	    $mac down-target $phy_tx	
+	    $mac set bandwidth_ $mac_bw; 
+	    $mac set TTI_ $mac_tti; 
+	    $mac start_TTI
+	    
+	    #
+	    # Physical Layer
+	    #
+
+	    $phy_tx node $self			;# Bind node <---> interface
+	    $phy_tx channel $outchan
+
+	} 
+
+    }
+}
+
+
+
+
+#===================================================================================================
+#
+#  The following are functions to set up tracing in the UMTS system.
+#
+#===================================================================================================
+
+
+Simulator instproc trace-rlc-queue { n1 n2 {file ""} } {
+    $self instvar link_ traceAllFile_
+    if {$file == ""} {
+	if ![info exists traceAllFile_] return
+	set file $traceAllFile_
+    }
+    $link_([$n1 id]:[$n2 id]) trace-rlc $self $file
+
+    # Added later for queue specific tracing events other than enque, 
+    # deque and drop 
+    set queue [$link_([$n1 id]:[$n2 id]) queue]
+    $queue attach-traces $n1 $n2 $file
+}
+
+
+SimpleLink instproc trace-rlc { ns f {op ""} } {
+
+    $self instvar enqT_ deqT_ drpT_ queue_ link_ fromNode_ toNode_
+    $self instvar rcvT_ ttl_ trace_
+    $self instvar drophead_		
+
+    set trace_ $f
+    set enqT_ [$ns create-trace UMTS/Enque $f $fromNode_ $toNode_ $op]
+    set deqT_ [$ns create-trace UMTS/Deque $f $fromNode_ $toNode_ $op]
+    set drpT_ [$ns create-trace UMTS/Drop $f $fromNode_ $toNode_ $op]
+    set rcvT_ [$ns create-trace UMTS/Recv $f $fromNode_ $toNode_ $op]
+
+    $self instvar drpT_ drophead_
+    set nxt [$drophead_ target]
+    $drophead_ target $drpT_
+    $drpT_ target $nxt
+
+    $queue_ drop-target $drophead_
+
+    #$drpT_ target [$queue_ drop-target]
+    #$queue_ drop-target $drpT_
+
+    $deqT_ target [$queue_ target]
+    $queue_ target $deqT_
+
+    # head is, like the drop-head_ a special connector.
+    # mess not with it.
+    $self add-to-head $enqT_
+
+    # put recv trace after ttl checking, so that only actually 
+    # received packets are recorded
+    $rcvT_ target [$ttl_ target]
+    $ttl_ target $rcvT_
+
+    $self instvar dynamics_
+    if [info exists dynamics_] {
+	$self trace-dynamics $ns $f $op
+    }
+}
+
+
+Node/UmtsNode instproc trace-outlink {f {index_ 0}} {
+    $self instvar id_ enqT_ deqT_ drpT_ hopT_ phy_tx_ mac_ nif_ nifs_ drophead_ tcm_ cs_ connector_ type_ nif_classifier_ bs_
+    
+    set ns [Simulator instance]
+    set fromNode_ $id_
+
+
+    if {$type_ == "ue" } {
+	if {[info exists tcm_($index_)] || [info exists connector_($index_)]} {
+	    set toNode_ 1
+	    set enqT_($index_) [$ns create-trace UMTS/Enque $f $fromNode_ $toNode_]
+	    $enqT_($index_) target $mac_($index_)
+	    if {[info exists tcm_($index_)]} {
+		$tcm_($index_) up-target $enqT_($index_)
+	    } else {
+		for {set i 0} {$i < $nifs_} {incr i} {
+
+		    if {[info exists tcm_($i)]} {
+			$tcm_($i) down-target $enqT_($index_)
+		    }
+		}
+
+		$connector_($index_) target $enqT_($index_)
+	    }
+
+	    set deqT_($index_) [$ns create-trace UMTS/Deque $f $fromNode_ $toNode_]
+	    $deqT_($index_) target $phy_tx_($index_)
+	    $mac_($index_) down-target $deqT_($index_)
+	    
+	    set drpT_($index_) [$ns create-trace UMTS/Drop $f $fromNode_ $toNode_]
+	    $drpT_($index_) target [$drophead_($index_) target]
+	    $drophead_($index_) target $drpT_($index_)
+	    $mac_($index_) drop-target $drpT_($index_)
+	} else {
+	    puts "UE: Stack $index_ at Node ID:$id_ is not outlink."
+	}
+
+    } elseif {$type_ == "rnc" } {
+	if {[info exists nif_($index_)]} {
+	    set toNode_ 1
+	    set hopT_($index_) [$ns create-trace UMTS/Hop $f $fromNode_ $toNode_]
+	    $hopT_($index_) target [$nif_($index_) target]
+	    $nif_($index_) target $hopT_($index_)
+	} else {
+	    puts "RNC: Stack $index_ at RNC ID:$id_ is not outlink."
+	}
+
+    } elseif {$type_ == "bs" } {
+	if {[info exists tcm_($index_)] || [info exists connector_($index_)]} {
+	    set toNode_ -1
+	    set enqT_($index_) [$ns create-trace UMTS/Enque $f $fromNode_ $toNode_]
+	    $enqT_($index_) target $mac_($index_)
+	    if {[info exists tcm_($index_)]} {
+		$tcm_($index_) up-target $enqT_($index_)
+	    } else {
+		for {set i 0} {$i < $nifs_} {incr i} {
+		    if {[info exists tcm_($i)]} {
+			$tcm_($i) down-target $enqT_($index_)
+		    }
+		}
+		
+		$connector_($index_) target $enqT_($index_)
+	    }
+
+	    set deqT_($index_) [$ns create-trace UMTS/Deque $f $fromNode_ $toNode_]
+	    $deqT_($index_) target $phy_tx_($index_)
+	    $mac_($index_) down-target $deqT_($index_)
+	    
+	    set drpT_($index_) [$ns create-trace UMTS/Drop $f $fromNode_ $toNode_]
+	    $drpT_($index_) target [$drophead_($index_) target]
+	    $drophead_($index_) target $drpT_($index_)
+	    $mac_($index_) drop-target $drpT_($index_)
+	} else {
+	    puts "BS: Stack $index_ at BS ID:$id_ is not outlink."
+	}
+    }
+}
+
+
+#
+# Trace element between mac and ll 
+#
+
+Node/UmtsNode instproc trace-inlink {f {index_ 0} } {
+    $self instvar id_ rcvT_ mac_ ll_ errT_ em_ type_ bs_
+
+    set ns [Simulator instance]
+    set toNode_ $id_
+    
+    if {$type_ == "rnc"} {
+	return
+    } elseif {$type_ == "ue"} {
+	set fromNode_ $bs_
+    } elseif {$type_ == "bs"} {
+	set fromNode_ -1
+    }
+
+    if {[info exists em_($index_)]} {
+	# if error model, then chain mac -> em -> rcvT -> ll
+	# First, set up an error trace on the ErrorModule
+	set errT_($index_) [$ns create-trace UMTS/Error $f $fromNode_ $toNode_]
+	$errT_($index_) target [$em_($index_) drop-target]
+	$em_($index_) drop-target $errT_($index_)
+	set rcvT_($index_) [$ns create-trace UMTS/Recv $f $fromNode_ $toNode_]
+	$rcvT_($index_) target [$em_($index_) target]
+	$em_($index_) target $rcvT_($index_)
+    } else {
+	if {[info exists mac_($index_)]} {
+	    set rcvT_($index_) [$ns create-trace UMTS/Recv $f $fromNode_ $toNode_]
+	    $rcvT_($index_) target [$mac_($index_) up-target]
+	    $mac_($index_) up-target $rcvT_($index_)
+	} else {
+	    puts"Stack $index_ at Node ID:$id_ is not valid."
+	}
+    }
+}
+
+
+Node/UmtsNode instproc trace-inlink-tcp {f {index_ 0} } {
+    $self instvar id_ rcvtcpT_ ll_ type_ bs_
+
+    set ns [Simulator instance]
+    set toNode_ $id_
+
+    if {$type_ == "bs"} {
+	return
+    } elseif {$type_ == "ue"} {
+	set fromNode_ $bs_
+    } elseif {$type_ == "rnc"} {
+	set fromNode_ 1
+    }
+    if {[info exists ll_($index_)]} {
+	set rcvtcpT_($index_) [$ns create-trace Recv $f $fromNode_ $toNode_]
+	$rcvtcpT_($index_) target [$ll_($index_) up-target]
+	$ll_($index_) up-target $rcvtcpT_($index_)
+    } else {
+	puts "Stack $index_ at Node ID:$id_ is not valid."
+    }
+}
+
+
+#  Attaches error model to interface "index" (by default, the first one)
+Node/UmtsNode instproc interface-errormodel { em { index 0 } } {
+    $self instvar mac_ em_ id_
+    if {[info exists mac_($index)]} {
+	$em target [$mac_($index) up-target]
+	$mac_($index) up-target $em
+	$em drop-target [new Agent/Null]; # otherwise, packet is only marked
+	set em_($index) $em
+    } else {
+	puts "Stack $index at Node ID:$id_ is not valid."
+    }
+}
+
+
+
+Node/UmtsNode instproc status-errormodel { em { index 0 } } {
+    $self instvar mac_ em_ id_
+    if {[info exists mac_($index)] && [info exists em_($index)]} {
+	set tano_ [new Tano]
+	$mac_($index) up-target $tano_
+	$tano_ up-target $em_($index)
+	$tano_ down-target $em 		
+	$em target [$em_($index) target]
+
+	$em drop-target [new Agent/Null]; # otherwise, packet is only marked
+    } else {
+	puts "Stack $index at Node ID:$id_ is not valid."
+    }
+}
+
+
+###########
+# TRACE MODIFICATIONS
+##########
+
+# This creates special UMTS tracing elements
+# Support for Enque, Deque, Recv, Drop, Hop and Error
+
+Class Trace/UMTS/Hop -superclass Trace/UMTS
+Trace/UMTS/Hop instproc init {} {
+    $self next "h"
+}
+
+Class Trace/UMTS/Enque -superclass Trace/UMTS
+Trace/UMTS/Enque instproc init {} {
+    $self next "+"
+}
+
+Class Trace/UMTS/Deque -superclass Trace/UMTS
+Trace/UMTS/Deque instproc init {} {
+    $self next "-"
+}
+
+Class Trace/UMTS/Recv -superclass Trace/UMTS
+Trace/UMTS/Recv instproc init {} {
+    $self next "r"
+}
+
+Class Trace/UMTS/Drop -superclass Trace/UMTS
+Trace/UMTS/Drop instproc init {} {
+    $self next "d"
+}
+
+Class Trace/UMTS/Error -superclass Trace/UMTS
+Trace/UMTS/Error instproc init {} {
+    $self next "e"
+}
+
+# HTTP Modification
+Http instproc umts-connect { server } {
+    Http instvar TRANSPORT_
+    $self instvar ns_ slist_ node_ fid_ id_
+
+    lappend slist_ $server
+    set tcp [new Agent/TCP/$TRANSPORT_]
+    $tcp set fid_ [$self getfid]
+    $ns_ attach-agent $node_ $tcp
+
+    set ret [$server alloc-connection $self $fid_]
+    set snk [$ret agent]
+    $ns_ connect $tcp $snk
+    #$tcp set dst_ [$snk set addr_]
+    $tcp set window_ 100
+
+    # Use a wrapper to implement application data transfer
+    set wrapper [new Application/TcpApp $tcp]
+    $self cmd connect $server $wrapper
+    $wrapper connect $ret
+    #puts "HttpApp $id_ connected to server [$server id]"
+
+    return $tcp
+}
+
diff -urN ns-2.30-orig/tools/coot.cc ns-2.30-eu112/tools/coot.cc
--- ns-2.30-orig/tools/coot.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/tools/coot.cc	2006-10-07 22:47:32.000000000 +0307
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2005 Twente Institute for Wireless and Mobile
+ *		Communications B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. or WMC may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id $
+ */
+
+
+#include "random.h"
+#include "trafgen.h"
+#include "ranvar.h"
+#include <stdlib.h>
+
+/* implement an on/off source with average on and off times taken
+ * from a pareto distribution.  (enough of these sources multiplexed
+ * produces aggregate traffic that is LRD).  It is parameterized
+ * by the average burst time, average idle time, burst rate, and
+ * pareto shape parameter and packet size.
+ */
+
+class COOT_Traffic : public TrafficGenerator {
+public:
+  COOT_Traffic();
+  virtual double next_interval(int&);
+  int on()  { return on_ ; }
+  int command(int argc, const char*const* argv);
+  
+protected:
+  void init();
+  double ontime_;  /* average length of burst (sec) */
+  double offtime_; /* average idle period (sec) */
+  double rate_;    /* send rate during burst (bps) */
+  double interval_; /* inter-packet time at burst rate */
+  double burstlen_; /* average # packets/burst */
+  double shape_;    /* pareto shape parameter */
+  unsigned int rem_; /* number of packets remaining in current burst */
+  double p1_;       /* parameter for pareto distribution to compute
+		     * number of packets in burst.
+		     */
+  int on_;          /* denotes whether in the on or off state */
+  int coot_ID_; 
+  RNG * rng_; /* If the user wants to specify his own RNG object */
+
+  ExponentialRandomVariable Offtime_;
+
+};
+
+
+static class COOTTrafficClass : public TclClass {
+public:
+  COOTTrafficClass() : TclClass("Application/Traffic/Coot") {}
+  TclObject* create(int, const char*const*) {
+    return (new COOT_Traffic());
+  }
+} class_coot_traffic;
+
+
+int COOT_Traffic::command(int argc, const char*const* argv){
+  
+  Tcl& tcl = Tcl::instance();
+  if(argc==3){
+    if (strcmp(argv[1], "use-rng") == 0) {
+      rng_ = (RNG*)TclObject::lookup(argv[2]);
+      if (rng_ == 0) {
+	tcl.resultf("no such RNG %s", argv[2]);
+	return(TCL_ERROR);
+      }                        
+      return (TCL_OK);
+    } else if (strcmp(argv[1], "coot-ID") == 0) {
+      coot_ID_ = atoi(argv[2]);
+      return (TCL_OK);
+    }
+  }
+  return Application::command(argc,argv);
+}
+
+
+COOT_Traffic::COOT_Traffic() : rng_(NULL)
+{
+  bind_time("burst_time_", &ontime_);
+  bind_time("idle_time_", &offtime_);
+  bind_bw("rate_", &rate_);
+  bind("shape_", &shape_);
+  bind("packetSize_", &size_);
+}
+
+void COOT_Traffic::init()
+{
+  interval_ = (double)(size_ << 3)/(double)rate_;
+  burstlen_ = ontime_/interval_;
+  rem_ = 0;
+  on_ = 0;
+  p1_ = burstlen_ * (shape_ - 1.0)/shape_;
+
+// Uncomment if you want TCP packets marked as "coot"
+// if (agent_)
+//    agent_->set_pkttype(PT_COOT);
+}
+
+double COOT_Traffic::next_interval(int& size)
+{
+  
+  double t = interval_;
+  
+  on_ = 1;
+  if (rem_ == 0) {
+    /* compute number of packets in next burst */
+    if(rng_ == 0){
+      rem_ = int(Random::pareto(p1_, shape_) + .5);
+    }
+    else{
+      rem_ = int(rng_->pareto(p1_, shape_) + .5);
+    }
+
+    /* make sure we got at least 1 */
+    if (rem_ == 0)
+      rem_ = 1;	
+    
+    /* start of an idle period, compute idle time */
+    if(rng_ == 0) {
+      t += Offtime_.value();
+    }
+    else {
+      t += double(rng_->exponential(offtime_));
+    }
+		  
+
+    //printf(" AVG IDLE VALUE: %f\n", offtime_);
+    //printf("%d\t %f\t %f\t %f\t %d\t %%COOT%d%%\n", coot_ID_, Scheduler::instance().clock(),t, ((rem_-1)*interval_), rem_, coot_ID_); 
+
+    on_ = 0;
+    
+  }
+  rem_--;
+  
+  size = size_;
+  return(t);
+   
+}
+
+
+
+
+
diff -urN ns-2.30-orig/trace/trace.cc ns-2.30-eu112/trace/trace.cc
--- ns-2.30-orig/trace/trace.cc	2006-09-25 08:18:03.000000000 +0307
+++ ns-2.30-eu112/trace/trace.cc	2006-10-07 22:50:14.000000000 +0307
@@ -198,7 +198,7 @@
 
 	/* UDP's now have seqno's too */
 	if (t == PT_RTP || t == PT_CBR || t == PT_UDP || t == PT_EXP ||
-	    t == PT_PARETO)
+	    t == PT_PARETO || t == PT_COOT)
 		seqno = rh->seqno();
         else if (t == PT_RAP_DATA || t == PT_RAP_ACK)
                 seqno = raph->seqno();
diff -urN ns-2.30-orig/umts/am-hs.cc ns-2.30-eu112/umts/am-hs.cc
--- ns-2.30-orig/umts/am-hs.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/am-hs.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,1208 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * Copyright (c) 2005 Twente Institute for Wireless and Mobile
+ *		Communications B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. or WMC may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: am-hs.cc,v 1.3 2005/09/22 15:07:08 simon Exp $
+ */
+
+#include "am-hs.h"
+#include "mac.h"
+#include "flags.h"
+#include "random.h"
+#include "address.h"
+#include "hsdpalink.h"
+#include "timer-handler.h"
+
+// These variables are used as 'super-globals', in this way the AM-HS object
+// and the MAC-hs object at the BS can be reached.
+
+RLC_HS     *rlc_address;        //= this;
+extern HsdpaMac *mac_address;   //defined in hsdpalink.cc
+
+static class AM_HSRlcClass:public TclClass {
+public:
+   AM_HSRlcClass():TclClass("UMTS/RLC/AMHS") {
+   } TclObject *create(int, const char *const *) {
+      return (new AM_HS);
+   }
+}
+
+class_am_hs;
+
+AM_HS::AM_HS():RLC_HS(), creditTimer_(this, RLC_TIMER_CREDIT)
+{
+   rlc_address = this;
+
+   bind("win_", &win_);
+   bind_time("temp_pdu_timeout_time_", &tempPDUTimeOutTime_);
+   bind("credit_allocation_interval_", &creditAllocationInterval_);
+   bind("flow_max_", &flowMax_);
+   bind("priority_max_", &priorityMax_);
+   bind("buffer_level_max_", &bufferLevelMax_);
+   bind("status_timeout_", &status_timeout_);
+   bind("payload_", &payloadSize_);
+   bind_time("TTI_", &TTI_);
+   bind("poll_PDU_", &poll_PDU_);
+   bind_time("poll_timeout_", &poll_timeout_);
+   bind_time("stprob_timeout_", &stprob_timeout_);
+   bind("length_indicator_", &length_indicator_);
+   bind("status_pdu_header_", &status_pdu_header_);
+   bind("min_concat_data_", &min_concat_data_);
+   bind("macDA_", &macDA_);
+
+
+   // Calculate the size in bytes of Length Indicator including the
+   // Extention bit. If a PDU consists of multiple parts, for each
+   // part these two fields are added to the header. If the PDU consists
+   // of only one part, these fields are omitted (9.2.1.4 + 9.2.2.5 from
+   // 3GPP TS 25.322 v5.6.0).
+   lengthIndicatorSize_ = ((length_indicator_ + 1) / 8);
+
+   // credit_allocation_interval_ is specified in numbers of TTIs, for our
+   // timer, we need it in seconds.
+   creditAllocationTimeoutInterval_ = TTI_ * creditAllocationInterval_;
+
+   // Initialize the vectors for the Flow Information and Transmission Buffers
+   for (int i = 0; i < flowMax_; i++) {
+      am_flow_information *temp = new am_flow_information(this, i);
+
+      memset(temp->seen_, 0, sizeof(temp->seen_));
+      for (int j = 0; j < priorityMax_; j++) {
+         umtsQueue  *temp2 = new umtsQueue;
+
+         temp->transmissionBuffer_.push_back(temp2);
+      }
+      flowInfo_.push_back(temp);
+   }
+
+   // schedule credit allocation timer for the first time
+   creditTimer_.sched(creditAllocationTimeoutInterval_);
+
+}
+
+
+int AM_HS::command(int argc, const char *const *argv)
+{
+   if (argc == 2) {
+      Tcl & tcl = Tcl::instance();
+      if (strcmp(argv[1], "TTI") == 0) {
+         tcl.resultf("%f", TTI_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "BW") == 0) {
+         tcl.resultf("%f", bandwidth_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "start_TTI") == 0) {
+         // do nothing (so ignore this methodcall, the timers are started by the
+         // constructor)
+         return TCL_OK;
+      }
+   } else if (argc == 3) {
+      if (strcmp(argv[1], "macDA") == 0) {
+         int nodeID = Address::instance().str2addr(argv[2]);
+
+         // The node-ids of the UEs start at 2, so decrease the node-id by two
+         // to get the flow-id
+         flowInfo_.at(nodeID - 2)->macDA_ = nodeID;
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "addr") == 0) {
+         address_ = Address::instance().str2addr(argv[2]);
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "daddr") == 0) {
+         int nodeID = Address::instance().str2addr(argv[2]);
+
+         // The node-ids of the UEs start at 2, so decrease the node-id by two
+         // to get the flow-id
+         flowInfo_.at(nodeID - 2)->d_address_ = nodeID;
+         return (TCL_OK);
+      }
+   }
+   int returnvalue = LL::command(argc, argv);
+
+
+   return returnvalue;
+}
+
+void AM_HS::recv(Packet * p, Handler * h)
+{
+
+
+   hdr_cmn    *ch = HDR_CMN(p);
+
+   // If the direction is up, we don't have to change anything, and the packet
+   // can be processed.
+   if (ch->direction() == hdr_cmn::UP) {
+      hdr_rlc    *llh = hdr_rlc::access(p);
+      int flowID = hdr_ip::access(p)->flowid();
+
+
+      if (llh->dst() != address_ || ch->error() > 0) {
+         // The packet was meant for another UE, or it contained errors. In
+         // both cases it will be dropped.
+         Packet::free(p);
+         return;
+      }
+      // Check the type op packets
+      if (llh->lltype() == RLC_BACK) {
+         // In case the packet is a bitmap acknowledgement, process it and then
+         // free it.
+         processBitmapAck(p);
+         Packet::free(p);
+      } else if (llh->lltype() == RLC_DATA || llh->lltype() == RLC_PB_BACK) {
+         // In case the packet is a piggybacked bitmap acknowledgement or a
+         // datapacket the data should be handled, possibly after the
+         // piggybacked bitmap acknowledgement is processed.
+         if (llh->lltype() == RLC_PB_BACK) {
+            processBitmapAck(p);
+         }
+         // Figure out if any SDUs can be handed up.
+         int numSDU = update(llh->seqno(), llh->eopno(), flowID);
+
+         // Check whether we can see that a PDU is missing. If that is the case
+         // we can already send a bitmap acknowledgement and we do not need to
+         // wait until the sender sends a poll for a bitmap acknowledgement.
+         checkForMissingPDU(p);
+
+         // We only store the last PDU of an SDU. The rest of the PDUs are not
+         // needed for the reassembly and can be freed.
+         if (llh->seqno() == llh->eopno() && numSDU >= 0) {
+            flowInfo_.at(flowID)->sduB_.orderedEnque(p);
+         } else {
+            Packet::free(p);
+         }
+         // Reassemble and send up the SDUs that are ready
+         if (numSDU > 0) {
+            makeSDU(numSDU, flowID);
+         }
+      } else {
+         // In case the type of the packet is something else, just drop it.
+         drop(p);               // Unknown type, inclusing Positive Acknowledgements
+      }
+      return;
+   } else {
+      // We think that this should always be the case, so why set it again? For
+      // testing purposes we should replace the following line by an assert
+      // statement to check it.
+      ch->direction() = hdr_cmn::DOWN;
+      sendDown(p);
+   }
+
+}
+
+void AM_HS::enqueInBackOfTransmissionBuffer(Packet * p)
+{
+
+  hdr_cmn *p_ch = HDR_CMN(p);
+
+
+   int flowID = hdr_ip::access(p)->flowid();
+   int priority = hdr_ip::access(p)->prio();
+
+
+
+   assert(!
+          ((flowInfo_.at(flowID)->transmissionBuffer_.at(priority)->length()) >=
+           bufferLevelMax_));
+
+   flowInfo_.at(flowID)->transmissionBuffer_.at(priority)->enque(p);
+
+
+}
+
+
+// This method will always enque the packet in the front of the queue. This
+// method is only called when packets are retransmitted.
+// For this reason we do not use the maximum buffer size, so in fact, the
+// maximum buffer size does not guarantee that the size of the buffer will
+// be smaller or equal to the maxmum buffersize, only that when the buffer
+// is full (has more or equal packets in it as the maximum buffersize) no
+// *new* packets are admitted.
+//
+// When this approach was not followed and packets were dropped from the back
+// of the queue when the buffersize was larger or equal to the maximum
+// buffersize the following occurs:
+//  - The buffer is full
+//  - A burst of packets is sent
+//  - Many new packets arrive and fill up the buffer again
+//  - Negative acknowledgements from the sent burst arrive, dropping many
+//    of the newly arived new packets, which will need to be retransmitted
+//    again.
+
+int AM_HS::enqueInFrontOfTransmissionBuffer(Packet * p)
+{
+// return 1 when succesfully enqueued, -1 when buffer is full and
+// a packet is dropped
+
+   int r_value = 1;
+
+
+   int flowID = hdr_ip::access(p)->flowid();
+   int priority = hdr_ip::access(p)->prio();
+
+
+   flowInfo_.at(flowID)->transmissionBuffer_.at(priority)->enqueUniqueFront(p);
+
+   return r_value;
+}
+
+//---------------------------
+// sendDown processes a SDU into PDUs for transmission to MAC-HS
+// if possible, waiting temporary packets are filled up.
+//---------------------------
+
+void AM_HS::sendDown(Packet * p)
+{
+
+   // First check whether the SDU fits into the transmission buffer completely
+
+   int numPDUs =
+         (int) ceil((double) hdr_cmn::access(p)->size() /
+                    (double) payloadSize_);
+
+   // check includes possible space for a temporary packet (+1).
+   if (1 + numPDUs +
+       flowInfo_.at(hdr_ip::access(p)->flowid())->transmissionBuffer_.
+       at(hdr_ip::access(p)->prio())->length() >= bufferLevelMax_) {
+      Packet::free(p);
+      return;
+   }
+
+   // Second check whether there is still a not-finished PDU available that can
+   // be used for concatenation.
+   handleTemporaryPacket(p);
+
+   while (p != NULL) {
+      // Each loop the front of the SDU is removed and send in a PDU. This
+      // results in a smaller and smaller SDU, until at some point in time
+      // it is completely gone. In that case p equals to NULL and the
+      // complete SDU is segmented.
+
+      int concat_data = 0;      // Number of bytes that can be used for concatenation
+      bool close_PDU = false;   // Defines whether this is the last PDU of an SDU.
+      int padding = 0;          // Number of bytes that have to be padded
+      bool force_length_indicator = false;
+      Packet     *c;            // The newly constructed PDU.
+
+      int p_size = hdr_cmn::access(p)->size();
+
+      close_PDU = p_size <= payloadSize_;
+      force_length_indicator = p_size < payloadSize_;
+
+      if (p_size <= (payloadSize_ - lengthIndicatorSize_)) {
+         // decide whether the remaining data is too big too keep
+         // in which case we send it on with padding
+         concat_data = payloadSize_ - p_size - 2 * lengthIndicatorSize_;
+         if (concat_data < min_concat_data_) {
+            concat_data = 0;
+            padding = payloadSize_ - p_size - lengthIndicatorSize_;
+         } else {
+            padding = 0;
+         }
+      }
+
+      if (close_PDU) {
+         // reuse packet p
+         c = p;
+         p = NULL;
+      } else {
+         // copy p's data into c and force concat_data and padding to 0
+         concat_data = 0;
+         padding = 0;
+         c = p->copy();
+      }
+
+
+      //initialise shortcuts to header info of packets c (and p)
+      hdr_cmn    *c_ch = HDR_CMN(c);
+      hdr_rlc    *c_llh = hdr_rlc::access(c);
+      hdr_ip     *c_iph = hdr_ip::access(c);
+      hdr_tcp    *c_tcph = hdr_tcp::access(c);
+      int flowID = c_iph->flowid();
+
+      hdr_cmn    *p_ch = NULL;
+      hdr_ip     *p_iph = NULL;
+      hdr_tcp    *p_tcph = NULL;
+
+      if (p != NULL) {
+         p_ch = HDR_CMN(p);
+         p_iph = hdr_ip::access(p);
+         p_tcph = hdr_tcp::access(p);
+      }
+
+      c_llh->lptype() = c_ch->ptype();
+      c_llh->lerror_ = c_ch->error();
+      c_llh->lts_ = c_ch->timestamp();
+
+      if (close_PDU) {
+
+         if (flowInfo_.at(flowID)->SDU_size_ > 0) {
+            c_llh->lsize_ = flowInfo_.at(flowID)->SDU_size_;
+         } else {
+            c_llh->lsize_ = c_ch->size();
+         }
+
+         flowInfo_.at(flowID)->SDU_size_ = -1;
+
+      } else if (flowInfo_.at(flowID)->SDU_size_ < 0) {
+         assert(p != NULL);
+         flowInfo_.at(flowID)->SDU_size_ = hdr_cmn::access(p)->size();
+      }
+
+      c_llh->lltype() = RLC_DATA;
+      c_llh->seqno() = -1;      // will be set at the moment the packet is realy sent
+      c_llh->dst() = flowInfo_.at(flowID)->d_address_;
+      c_llh->src() = address_;
+      c_llh->lengthInd_ = 0;
+
+      if (close_PDU) {
+         // c_llh->eopno_ needs to be set to c_llh->seqno_. However, at this
+         // moment the seqno is not known yet. So, set it to EOPNO_TO_SEQNO
+         // and check when seqno is set whether eopno is EOPNO_TO_SEQNO. If this
+         // is the case eopno can be replaced by seqno.
+         c_llh->eopno_ = EOPNO_TO_SEQNO;
+      } else {
+         c_llh->eopno_ = EOPNO_NOT_EOP;
+      }
+
+      if (concat_data || padding || force_length_indicator) {
+         c_llh->lengthInd_++;
+      }
+      // The payload_ field is used to define the size of the parts between the
+      // different length indicators. The first element is used for the size of
+      // the part for the first SDU. In case concatenation occurs, the second
+      // element indicates the size of the part used for the second SDU. In case
+      // a status PDU is piggybacked, the last element (so, without concatenation
+      // the second, with concatenation the third) is used to indicate the size
+      // of the status PDU.
+
+      if (close_PDU) {
+         c_llh->payload_[PAYLOAD_FLD1] = c_ch->size();
+      } else {
+         if (force_length_indicator) {
+            c_llh->payload_[PAYLOAD_FLD1] = payloadSize_ - lengthIndicatorSize_;
+         } else {
+            c_llh->payload_[PAYLOAD_FLD1] = payloadSize_;
+         }
+      }
+      c_llh->payload_[PAYLOAD_FLD2] = 0;
+      c_llh->payload_[PAYLOAD_FLD3] = 0;
+
+      c_llh->padding_ = padding; //padding will always have the correct value here
+
+      // WTF? this is really ugly, bad things will happen here!
+      char       *mh = (char *) c->access(hdr_mac::offset_);
+      struct hdr_mac *c_dh = (struct hdr_mac *) mh;
+
+      c_ch->ptype() = PT_AMDA;
+      c_dh->macDA_ = flowInfo_.at(flowID)->macDA_;
+      c_dh->macSA_ = -1;
+      c_dh->hdr_type() = ETHERTYPE_RLC;
+      c_ch->timestamp() = Scheduler::instance().clock();
+
+      // Do we have space left over for concatenation?
+      if (close_PDU) {
+         if (concat_data) {
+            // Store the current packet and do not send it down.
+            // Because this is also the last part of the SDU we can
+            // stop this method.
+            c_llh->lengthInd_++;
+
+            StoreTemporaryPacket(c, concat_data);
+            break;              //exit while loop
+         }
+      } else {
+         // reduce the size of the SDU by an amount of the
+         // payload that will be sent in this PDU.
+         p_ch->size() = p_ch->size() - c_llh->payload_[PAYLOAD_FLD1];
+
+         assert(c_iph->flowid() == p_iph->flowid());
+         assert(c_iph->saddr() == p_iph->saddr());
+
+         assert(c_tcph->seqno() == p_tcph->seqno());
+      }
+
+      assert(c_ch->error() == 0);
+
+
+      c_ch->size() = payloadSize_;
+
+
+
+
+      // Finally, enque the packet in the transmission buffer.
+      enqueInBackOfTransmissionBuffer(c);
+
+   }
+
+
+}
+
+// This method is called when a PDU is created that is not full, and just stores
+// the PDU into a vector that will be inspected
+
+void AM_HS::StoreTemporaryPacket(Packet * p, int concat_data)
+{
+
+
+   temporaryPacket *temp = new temporaryPacket(this);
+
+   temp->p = p;
+   temp->concat_data = concat_data;
+   // We can't wait forever, because then we have a problem at the end of a
+   // burst of traffic: then the last PDU won't be send, causing timeouts and
+   // retransmissions. So, we do want to send the incomplete packet anyway
+   // at some point in time.
+   temp->tempPDUTimer.sched(tempPDUTimeOutTime_);
+   temporaryPackets_.push_back(temp);
+}
+
+
+// This method is called at the beginning of each arriving SDU. It checks
+// whether a packet with the same flow-id and priority that isn't complete
+// yet is waiting for concatenation. If it finds one, concatenation occurs
+// if possible. If this is not possible the waiting PDU is stored in the
+// transmission buffer. When concatenation occurs, the waiting packet is
+// filled, and is sent; the size of the newly arrived SDU is decreased by
+// the number of concatenated bytes. After this method, sendSDU continues
+// segmenting the SDU into PDUs.
+
+void AM_HS::handleTemporaryPacket(Packet * p)
+{
+
+
+   if (p == NULL) {
+      return;
+   }
+   // get the flow-id and priority for the current PDU
+   int flowID = hdr_ip::access(p)->flowid();
+   int priority = hdr_ip::access(p)->prio();
+
+
+   // Search all current temporary PDUs to find a temporary PDU with
+   // the same flow-id and priority
+   for (unsigned int i = 0; i < temporaryPackets_.size(); i++) {
+
+
+      if (hdr_ip::access(temporaryPackets_.at(i)->p)->flowid() == flowID
+          && hdr_ip::access(temporaryPackets_.at(i)->p)->prio() == priority) {
+         // We have found one
+
+         // Fill the temporary PDU with data from the new SDU, and delete that
+         // part of the SDU. Then store the temporary PDU in the Transmission
+         // and Retransmission Buffers and return the remaining part of the SDU.
+
+         // Concatenation (3GPP TS 25.301 5.3.2.2): If the contents of an RLC
+         // SDU cannot be carried by one RLC PDU, the first segment of the next
+         // RLC SDU may be put into the RLC PDU in concatenation with the last
+         // segment of the previous RLC SDU.
+
+         if (hdr_cmn::access(p)->size() > payloadSize_) {
+
+            hdr_rlc::access(temporaryPackets_.at(i)->p)->payload_[1] =
+                  temporaryPackets_.at(i)->concat_data;
+
+            // this variable was previously set in makePDU, it holds the
+            // original SDU size.
+            flowInfo_.at(hdr_ip::access(p)->flowid())->SDU_size_ =
+                  hdr_cmn::access(p)->size();
+            hdr_cmn::access(p)->size() =
+                  hdr_cmn::access(p)->size() -
+                  temporaryPackets_.at(i)->concat_data;
+
+         } else {
+            // We cannot concatenate: decrease the number of length indicators
+            // (it has already been updated because we would expect that
+            // concatenation would happen), and add padding to the packet.
+            hdr_rlc::access(temporaryPackets_.at(i)->p)->lengthInd_--;
+            hdr_rlc::access(temporaryPackets_.at(i)->p)->padding_ =
+                  temporaryPackets_.at(i)->concat_data + lengthIndicatorSize_;
+         }
+
+         //NEILL: Set temp packet to full payload size??
+         hdr_cmn::access(temporaryPackets_.at(i)->p)->size() = payloadSize_;
+         //****************************************************************
+
+
+         enqueInBackOfTransmissionBuffer(temporaryPackets_.at(i)->p);
+
+         // Now the temporary PDU has been sent, delete the timer
+         // so that the timeout will not occur anymore.
+         temporaryPackets_.at(i)->tempPDUTimer.cancel();
+         temporaryPackets_.erase((temporaryPackets_.begin() + i));
+         return;
+
+      }
+   }
+}
+
+
+void AM_HS::timeout(int tno, int flowID)
+{
+   vector < int >temp_vect;
+
+
+   switch (tno) {
+     case RLC_TIMER_POLL:
+        for (unsigned int i = 0; i < flowInfo_.size(); i++) {
+           if (Scheduler::instance().clock() >=
+               flowInfo_.at(i)->poll_timer_.timeOfExpiry()
+               && (flowInfo_.at(i)->poll_timer_.status() == TIMER_PENDING
+                   || flowInfo_.at(i)->poll_timer_.status() ==
+                   flowInfo_.at(i)->poll_timer_.TIMER_HANDLING)) {
+              if (flowInfo_.at(i)->maxseq_ == flowInfo_.at(i)->FSN_
+                  && flowInfo_.at(i)->b_bal_ == 0) {
+                 // If no outstanding data, then don't do anything.
+                 return;
+              }
+              flowInfo_.at(i)->poll_seq_ = -1;
+              flowInfo_.at(i)->set_poll_ = 1;
+           }
+        }
+
+        break;
+     case RLC_TIMER_STPROB:
+        for (unsigned int i = 0; i < flowInfo_.size(); i++) {
+           if (Scheduler::instance().clock() >=
+               flowInfo_.at(i)->stprob_timer_.timeOfExpiry()
+               && (flowInfo_.at(i)->stprob_timer_.status() == TIMER_PENDING
+                   || flowInfo_.at(i)->stprob_timer_.status() ==
+                   flowInfo_.at(i)->poll_timer_.TIMER_HANDLING)) {
+              if (flowInfo_.at(i)->prohibited_) {
+                 flowInfo_.at(i)->send_status_ = 1;
+                 flowInfo_.at(i)->prohibited_ = 0;
+                 flowInfo_.at(i)->sinfo_timer_.sched(status_timeout_);
+              }
+           }
+        }
+        break;
+     case RLC_TIMER_TEMP_PDU:
+        // Walk through all temporary PDUs and check whether their
+        // timeout-time is the same as the current time or lies in the
+        // past (actually, this shouldn't happen). If that is the case
+        // send those PDUs and remove them from the vector.
+        for (unsigned int i = 0; i < temporaryPackets_.size(); i++) {
+
+           // For performance reasons it might be a good idea to
+           // not only select the temporary PDUs that have to be sent
+           // now, but also the PDUs that are due within a small
+           // period in time, so that timeouts do not occur that
+           // often anymore.
+           if (Scheduler::instance().clock() >=
+               temporaryPackets_.at(i)->tempPDUTimer.timeOfExpiry()) {
+              // We have found one
+
+              // Before we stored the temporary PDU in the
+              // vector, we set the number of Length Indicators
+              // and the number of bytes that could be
+              // concatenated. Because we are not concatenating,
+              // but padding we need one Length Indicator less,
+              // thus we have to pad more.
+              hdr_rlc::access(temporaryPackets_.at(i)->p)->lengthInd_--;
+              hdr_rlc::access(temporaryPackets_.at(i)->p)->padding_ =
+                    temporaryPackets_.at(i)->concat_data + lengthIndicatorSize_;
+
+              //NEILL: set packet size to full payload size
+              hdr_cmn::access(temporaryPackets_.at(i)->p)->size() = payloadSize_;
+              //****************************************************************
+
+              enqueInBackOfTransmissionBuffer(temporaryPackets_.at(i)->p);
+              temporaryPackets_.erase((temporaryPackets_.begin() + i));
+              i--;              // otherwise the next temporary packet will be skipped
+           }
+        }
+        break;
+     case RLC_TIMER_CREDIT:
+        // Send a credit allocation request to the MAC-hs. And reschedule
+        // the timer
+
+        // Create a vector with the length of the Transmission Buffers, and
+        // send this vector to the MAC-hs.
+
+        //Note: Buffers indexed: f1p1,f2p1,f3p1,f1p2,f2p2,f3p2,f1p3...
+
+
+        for (int i = 0; i < priorityMax_; i++) {
+           for (int j = 0; j < flowMax_; j++) {
+              temp_vect.push_back(flowInfo_.at(j)->transmissionBuffer_.at(i)->
+                                  length());
+
+
+           }
+        }
+
+        mac_address->cred_alloc(&temp_vect);
+
+
+        // Reschedule
+        creditTimer_.resched(creditAllocationTimeoutInterval_);
+        break;
+     case RLC_TIMER_STATUS:
+        // When this timer times out, the status information that needs to be sent
+        // can't be delayed anymore. So, now we have to construct a Status PDU and
+        // send it using the highest priority.
+        for (unsigned int i = 0; i < flowInfo_.size(); i++) {
+           if (Scheduler::instance().clock() >=
+               flowInfo_.at(i)->sinfo_timer_.timeOfExpiry()
+               && (flowInfo_.at(i)->sinfo_timer_.status() == TIMER_PENDING
+                   || flowInfo_.at(i)->sinfo_timer_.status() ==
+                   flowInfo_.at(i)->poll_timer_.TIMER_HANDLING)) {
+              Packet     *p = createBitmapAck(i);
+
+              enqueInBackOfTransmissionBuffer(p);
+              flowInfo_.at(i)->stprob_timer_.resched(stprob_timeout_);
+           }
+        }
+        break;
+     default:
+
+        break;
+   }
+
+}
+
+
+// This method is called just before a packet is really sent. It does:
+//   - It checks whether the poll bit needs to be set
+//   - It sets the sequence number
+
+void AM_HS::completePDU(Packet * p)
+{
+
+
+   hdr_rlc    *llh = hdr_rlc::access(p);
+   int flowID = hdr_ip::access(p)->flowid();
+
+   // Check whether we have to poll for a bitmap status update. This is true
+   // when it is explicitly defined by the field set_poll_ that can be set by
+   // other methods, or when the number of transmitted PDUs is a multiplicity
+   // of poll_PDU_ (the 'Poll every X PDU' setting).
+   if (flowInfo_.at(flowID)->set_poll_ == 1
+       || flowInfo_.at(flowID)->tx_PDUs_ > poll_PDU_) {
+      hdr_rlc::access(p)->poll() = true;
+      flowInfo_.at(flowID)->set_poll_ = 0;
+      flowInfo_.at(flowID)->tx_PDUs_ = 0;
+      if ((hdr_rlc::access(p)->seqno() >= flowInfo_.at(flowID)->poll_seq_)
+          || (flowInfo_.at(flowID)->poll_timer_.status() != TIMER_PENDING)) {
+         flowInfo_.at(flowID)->poll_seq_ = hdr_rlc::access(p)->seqno();
+         // Because a poll will be send, cancel the poll timer and reschedule
+         // it.
+         flowInfo_.at(flowID)->poll_timer_.resched(poll_timeout_);
+      }
+   }
+   // If the packet is transmitted for the first time, set the sequence number
+   // and possibly the End Of Packet (eop) number.
+   if (llh->seqno() == -1) {
+      llh->seqno() = flowInfo_.at(flowID)->seqno_;
+      flowInfo_.at(flowID)->seqno_++;
+      if (llh->eopno() == EOPNO_TO_SEQNO) {
+         llh->eopno() = llh->seqno();
+      }
+   }
+   return;
+}
+
+// This method is called just before a packet is really sent. It does:
+//   - It tries to piggyback status information
+
+void AM_HS::insertStatusInformation(Packet * p)
+{
+
+
+   hdr_cmn    *ch = hdr_cmn::access(p);
+   hdr_rlc    *llh = hdr_rlc::access(p);
+   int flowID = hdr_ip::access(p)->flowid();
+
+   // If the type of the packet is something else than AM_Data, don't do
+   // anything with it, otherwise we might piggyback a bitmap ack on top
+   // of a bitmap ack.
+   if (ch->ptype() == PT_AMDA) {
+      // Check whether a Bitmap Ack is due to be sent and if so, whether it can
+      // be piggybacked.
+      if (flowInfo_.at(flowID)->send_status_ == 1) {
+
+         if (llh->padding_ >= StatusPDUSize(flowID)) {
+            p = createBitmapAck(flowID, p);
+            flowInfo_.at(flowID)->send_status_ = 0;
+            if (flowInfo_.at(flowID)->sinfo_timer_.status() == TIMER_PENDING) {
+               flowInfo_.at(flowID)->sinfo_timer_.cancel();
+            }
+            flowInfo_.at(flowID)->stprob_timer_.resched(stprob_timeout_);
+         }
+      }
+   }
+}
+
+
+// This method is called by the MACHS to update the current credit allocation
+// values. After that, schedule the first packet.
+
+void AM_HS::credit_update(vector < int >new_rlc_credits)
+{
+
+
+
+   vector < int >highestPriority;
+   int        *highestNonEmptyQueue = new int;
+
+   // Check in what PDU the poll bit should be set. It should be set in the
+   // last packet that will be sent for each flow. This loop is constructed
+   // different from the normal loops that loop through the flow-priority
+   // combinations, because we now have to calculate things per flow, so this
+   // flow needs to be in the outer-loop.
+   for (int f_count = 0; f_count < flowMax_; f_count++) {
+      *highestNonEmptyQueue = -1;   //-1 no full prio queue detected yet
+      for (int p_count = 0; p_count < priorityMax_; p_count++) {
+         if (new_rlc_credits.at(p_count * flowMax_ + f_count) > 0) {
+            *highestNonEmptyQueue = p_count; //set highest to p_count.
+         }
+      }
+      highestPriority.push_back(*highestNonEmptyQueue);
+   }
+
+   // For each buffer, transmit the number of PDUs defined in the credit
+   // allocation vector.
+   for (int p_count = 0; p_count < priorityMax_; p_count++) {
+      for (int f_count = 0; f_count < flowMax_; f_count++) {
+         for (int k = 1; k <= new_rlc_credits.at(p_count * flowMax_ + f_count);
+              k++) {
+            //Note: Buffers indexed: f1p1,f2p1,f3p1,f1p2,f2p2,f3p2,f1p3...
+
+            Packet     *p;
+
+            // AM-HS may not send packets that have a sequence number that
+            // is more than the windowsize more than the sequence number of the
+            // first packet that hasn't been acknowledged yet.
+            if (flowInfo_.at(f_count)->FSN_ + win_ <
+                flowInfo_.at(f_count)->seqno_) {
+               // Ignore all packets but acknowledgements (the packets that
+               // already have their sequence number set)
+               p = flowInfo_.at(f_count)->transmissionBuffer_.at(p_count)->
+                     dequeFirstSendable();
+            } else {
+               // The next sequence number will be inside the transmission
+               // window, so we can just send the first packet.
+               p = flowInfo_.at(f_count)->transmissionBuffer_.at(p_count)->
+                     deque();
+            }
+
+            if (p != NULL) {
+
+               // Check whether we should set the poll-bit in this PDU
+               if (k == new_rlc_credits.at(p_count * flowMax_ + f_count)
+                   && p_count == highestPriority.at(f_count)) {
+                  flowInfo_.at(f_count)->set_poll_ = 1;
+               }
+               // Check whether the packet that has been chosen
+               // has some space left that can be used for
+               // biggybacking.
+               completePDU(p);
+
+               // store a copy for possible retransmissions
+               flowInfo_.at(f_count)->retransmissionBuffer_.enque(p->copy());
+
+               insertStatusInformation(p);
+
+               // Actually send the packet down.
+               downtarget_->recv(p);
+
+               // Increase the number of PDUs sent. This is used for adding the
+               // poll bit each poll_pdu_ packets.
+               flowInfo_.at(f_count)->tx_PDUs_++;
+            } else {
+               // The number of packets available in the queue was smaller than
+               // the maximum number of packets that we were allowed to send to
+               // the Mac-hs. Or the RLC Window has blocked the packet from being sent.
+	       // We therefore deallocate the previously allocated credit.
+	       
+	          mac_address->remove_credit_allocation(p_count * flowMax_ + f_count);
+	                                    
+               // break;
+            }
+         }
+      }
+   }
+}
+
+
+// This method is used for the receiver based 'Check for missing PDJU' status
+// timer setting. See 9.7.2 of 3GPP TS 25.322 v5.6.0.
+
+void AM_HS::checkForMissingPDU(Packet * opkt)
+{
+
+
+
+   int flowID = hdr_ip::access(opkt)->flowid();
+
+
+   int first_missing = 0;
+
+   if (flowInfo_.at(flowID)->prohibited_) {
+      return;
+   }
+   // opkt is the "old" PDU that was received
+   if (flowInfo_.at(flowID)->stprob_timer_.status() == TIMER_PENDING) {
+      if (hdr_rlc::access(opkt)->poll()) {
+         flowInfo_.at(flowID)->prohibited_ = 1;
+      }
+      return;
+   }
+   // find first missing PDU in seen_ from next_ expected PDU
+   int i;
+
+   // WARNING: possible endless loop
+   for (i = flowInfo_.at(flowID)->next_; flowInfo_.at(flowID)->seen_[i & MWM]
+        != 0; i++) {
+      // do nothing
+   }
+   first_missing = i;
+
+   if (first_missing < flowInfo_.at(flowID)->maxseen_
+       || hdr_rlc::access(opkt)->poll()) {
+      if (flowInfo_.at(flowID)->send_status_ == 1) {
+         // Do nothing since a status report is already pending.
+      } else {
+         // Schedule a timeout for the status PDU to be sent. During the current
+         // time and the timeout the status information can be piggybacked, then
+         // this timer should be canceled.
+         flowInfo_.at(flowID)->sinfo_timer_.sched(status_timeout_);
+         flowInfo_.at(flowID)->send_status_ = 1;
+      }
+   }
+}
+
+Packet     *AM_HS::createBitmapAck(int flowID, Packet * p)
+{
+
+
+
+   hdr_rlc    *llh;
+   hdr_cmn    *ch;
+
+   int first_missing = flowInfo_.at(flowID)->next_;
+
+   while (flowInfo_.at(flowID)->seen_[first_missing & MWM]) {
+      ++first_missing;
+   }
+
+
+   int fsn = first_missing - 1;
+
+   if (fsn < 0) {
+      // When the first packet ever gets a nack we shouldn't try to ack
+      // everything until then.
+      fsn = 0;
+   }
+
+   if (p == NULL) {
+      p = Packet::alloc();
+
+      ch = hdr_cmn::access(p);
+
+      ch->uid() = 0;
+      ch->error() = 0;
+      ch->timestamp() = Scheduler::instance().clock();
+      ch->iface() = UNKN_IFACE.value();
+      ch->direction() = hdr_cmn::DOWN;
+
+      llh = hdr_rlc::access(p);
+
+
+
+      hdr_ip     *iph = hdr_ip::access(p);
+      hdr_tcp    *tcph = hdr_tcp::access(p);
+      char       *mh = (char *) p->access(hdr_mac::offset_);
+
+      llh->lltype() = RLC_BACK;
+      llh->dst() = flowInfo_.at(flowID)->d_address_;
+      llh->src() = address_;
+      llh->seqno() = fsn;
+      llh->lengthInd_ = 0;
+      llh->padding_ = payloadSize_ - StatusPDUSize(flowID);
+
+
+      for (int i = 1; i < 3; i++) {
+         llh->payload_[i] = 0;
+      }
+
+      llh->payload_[0] = StatusPDUSize(flowID);
+
+      iph->flowid() = flowID;   // set it to the current flowID
+      iph->prio() = 0;          // set it to the highest priority
+
+      iph->saddr() = -1;        // Because Bitmap acknowledgements are not passed
+      iph->sport() = -1;        // up until the IP layer, these fields do not need
+      iph->daddr() = -1;        // to be set.
+      iph->dport() = -1;
+      iph->ttl() = 32;
+
+      tcph->seqno() = -1;
+
+      ch->ptype() = PT_AMBA;
+      ch->size() = payloadSize_;
+
+      struct hdr_mac *dh = (struct hdr_mac *) mh;
+
+      dh->macDA_ = flowInfo_.at(flowID)->macDA_;
+      dh->macSA_ = -1;
+      dh->hdr_type() = ETHERTYPE_RLC;
+
+   } else {
+      llh = hdr_rlc::access(p);
+      ch = hdr_cmn::access(p);
+
+
+      // Look for the first payload-field that is empty and insert the
+      // status information there.
+      if (llh->payload_[PAYLOAD_FLD2] == 0) {
+         llh->payload_[PAYLOAD_FLD2] = StatusPDUSize(flowID);
+      } else {
+         llh->payload_[PAYLOAD_FLD3] = StatusPDUSize(flowID);
+      }
+      llh->padding_ = llh->padding_ - StatusPDUSize(flowID);
+      llh->lltype() = RLC_PB_BACK;
+      ch->ptype() = PT_AMPBBA;
+   }
+
+   llh->FSN() = fsn;
+   if ((flowInfo_.at(flowID)->maxseen_ - fsn + 1) >
+       (payloadSize_ * 8 - status_pdu_header_)) {
+      llh->length() = payloadSize_ * 8 - status_pdu_header_;
+   } else {
+      llh->length() = flowInfo_.at(flowID)->maxseen_ - fsn + 1;
+   }
+
+
+   llh->bitmap_ = new int[llh->length()];
+
+   // Basically, copy the seen_ array to the bitmap
+   for (int i = 0; i < llh->length(); i++) {
+      flowInfo_.at(flowID)->seen_[(fsn + i) & MWM]
+            ? llh->bitmap(i) = 1 : llh->bitmap(i) = 0;
+   }
+
+   return p;
+}
+
+
+// This method does not comply to the Bitmap acknowledgement mode defined in
+// 3GPP  TS 25.322 V5.6.0 (page 34).
+
+void AM_HS::processBitmapAck(Packet * p)
+{
+
+
+   hdr_rlc    *llh = hdr_rlc::access(p);
+   int flowID = hdr_ip::access(p)->flowid();
+
+   flowInfo_.at(flowID)->b_bal_ = 0;
+   flowInfo_.at(flowID)->length_ = llh->length();
+   flowInfo_.at(flowID)->FSN_ = llh->FSN();
+
+
+   flowInfo_.at(flowID)->retransmissionBuffer_.dropTill(flowInfo_.at(flowID)->
+                                                        FSN_);
+
+
+   // Start at the end of the bitmap and work your way through it. The reason
+   // why we start at the end is because packets that are retransmitted should
+   // have higher priority than packets that are transmitted for the first time.
+   // Packets that are retransmitted are inserted at the front of the
+   // transmission queue. When we start at the end of the bitmap, at the end
+   // the new packets that need to be retransmitted are then inserted in
+   // the correct order in the front of the queue. Otherwise, packets with
+   // higher sequence numbers are transmitted earlier, causing new bitmap
+   // acknowledgements to be send.
+
+   for (int i = flowInfo_.at(flowID)->length_ - 1; i >= 0; i--) {
+      if (llh->bitmap(i) == 0) {
+         Packet     *r =
+               flowInfo_.at(flowID)->retransmissionBuffer_.dequeCopy(flowInfo_.
+                                                                     at
+                                                                     (flowID)->
+                                                                     FSN_ + i);
+         flowInfo_.at(flowID)->b_bal_++;
+         assert(r != NULL);
+         enqueInFrontOfTransmissionBuffer(r);
+      }
+   }
+   delete[]llh->bitmap_;
+
+   flowInfo_.at(flowID)->highest_ack_ =
+         flowInfo_.at(flowID)->FSN_ + flowInfo_.at(flowID)->length_ - 1;
+   if (flowInfo_.at(flowID)->highest_ack_ >= flowInfo_.at(flowID)->poll_seq_) {
+      flowInfo_.at(flowID)->poll_timer_.force_cancel();
+      flowInfo_.at(flowID)->poll_seq_ = -1;
+      flowInfo_.at(flowID)->set_poll_ = 0;
+   }
+}
+
+// Returns the size of a Status PDU when it would have been constructed now.
+
+int AM_HS::StatusPDUSize(int flowID)
+{
+
+
+
+   int first_missing = flowInfo_.at(flowID)->next_;
+
+   while (flowInfo_.at(flowID)->seen_[first_missing & MWM]) {
+      ++first_missing;
+   }
+
+   int fsn = first_missing - 1;
+   int bits = flowInfo_.at(flowID)->maxseen_ - fsn + status_pdu_header_;
+
+   int bytes;
+
+   if (bits % 8) {
+      bytes = bits / 8 + 1;
+   } else {
+      bytes = bits / 8;
+   }
+   return bytes;
+}
+
+// returns number of SDUs that can be "delivered" to the Agent
+// also updates the receive window (i.e. next_, maxseen, and seen_ array)
+
+int AM_HS::update(int seq, int eopno, int flowID)
+{
+   int numSDU = 0;
+   bool just_marked_as_seen = FALSE;
+
+   // start by assuming the segment hasn't been received before
+
+   if (seq - flowInfo_.at(flowID)->next_ >= MWM) {
+      // next_ is next PDU expected; MWM is the maximum
+      // window size minus 1; if somehow the seqno of the
+      // PDU is greater than the one we're expecting+MWM,
+      // then ignore it.
+      return -1;
+   }
+
+   if (seq > flowInfo_.at(flowID)->maxseen_) {
+      // the PDU is the highest one we've seen so far
+      int i;
+
+      for (i = flowInfo_.at(flowID)->maxseen_ + 1; i < seq; ++i) {
+         flowInfo_.at(flowID)->seen_[i & MWM] = 0;
+      }
+      // we record the PDUs between the old maximum and
+      // the new max as being "unseen" i.e. 0
+      flowInfo_.at(flowID)->maxseen_ = seq;
+      if (seq == eopno) {
+         flowInfo_.at(flowID)->seen_[flowInfo_.at(flowID)->maxseen_ & MWM] = 1;
+      } else {
+         flowInfo_.at(flowID)->seen_[flowInfo_.at(flowID)->maxseen_ & MWM] = 2;
+      }
+      // set this PDU as being "seen".
+      flowInfo_.at(flowID)->seen_[(flowInfo_.at(flowID)->maxseen_ + 1) & MWM] =
+            0;
+      // clear the array entry for the PDU immediately
+      // after this one
+      just_marked_as_seen = TRUE;
+      // necessary so this PDU isn't confused as being a duplicate
+   }
+   int next = flowInfo_.at(flowID)->next_;
+
+   if (seq < next) {
+      // Duplicate PDU case 1: the PDU is to the left edge of
+      // the receive window; therefore we must have seen it
+      // before
+      return -1;
+   }
+
+   if (seq >= next && seq <= flowInfo_.at(flowID)->maxseen_) {
+      // next is the left edge of the recv window; maxseen_
+      // is the right edge; execute this block if there are
+      // missing PDUs in the recv window AND if current
+      // PDU falls within those gaps
+
+      if (flowInfo_.at(flowID)->seen_[seq & MWM] && !just_marked_as_seen) {
+         // Duplicate case 2: the segment has already been
+         // recorded as being received (AND not because we just
+         // marked it as such)
+         return -1;
+      }
+      if (seq == eopno) {
+         flowInfo_.at(flowID)->seen_[seq & MWM] = 1;
+      } else {
+         flowInfo_.at(flowID)->seen_[seq & MWM] = 2;
+      }
+      // record the PDU as being seen
+
+      while (flowInfo_.at(flowID)->seen_[next & MWM]) {
+         // This loop sees if any SDUs can now be deliver to
+         // the Agent due to this PDU arriving
+         next++;
+         if ((flowInfo_.at(flowID)->seen_[(next - 1) & MWM] == 1)) {
+            flowInfo_.at(flowID)->next_ = next;
+            // store the new left edge of the window
+            numSDU++;
+         }
+      }
+   }
+   return numSDU;
+}
+
+
+// Reassembles the received PDUs into an SDU and sends it up.
+
+void AM_HS::makeSDU(int numSDU, int flowID)
+{
+   Packet     *p;
+   hdr_cmn    *ch;
+   hdr_rlc    *llh;
+
+   for (int i = 0; i < numSDU; i++) {
+      p = flowInfo_.at(flowID)->sduB_.deque();
+      assert(p);
+      ch = HDR_CMN(p);
+      llh = hdr_rlc::access(p);
+
+      ch->ptype() = llh->lptype();
+      ch->error() = llh->lerror();
+      ch->timestamp() = llh->lts();
+      ch->size() = llh->lsize();
+
+      uptarget_ ? sendUp(p) : Packet::free(p);
+   }
+}
+
+
diff -urN ns-2.30-orig/umts/am-hs.h ns-2.30-eu112/umts/am-hs.h
--- ns-2.30-orig/umts/am-hs.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/am-hs.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: am-hs.h,v 1.45 2004/01/30 10:10:13 wtdavid Exp $
+ */
+
+#ifndef ns_am_hs_h
+#define ns_am_hs_h
+
+#include "rlc.h"
+#include "umts-timers.h"
+#include "umts-queue.h"
+#include <vector>
+
+#define MWS 4096             // max window size
+#define MWM (MWS-1)          // The "win_" parameter, representing the RLC window,
+                     // should be less than equal to MWM.
+
+#define EOPNO_NOT_EOP -1
+#define EOPNO_TO_SEQNO -2
+// When PDUs are formed and stored into the transmission buffer, the sequence
+// number is not yet known (for example, it is possible that data with higher
+// priority, or status information is send before this PDU). The eopno field
+// cannot be set to the seqno in this case at that moment, so in case the PDU
+// is the last PDU in the SDU the eopno field is set to a temporary value
+// (EOPNO_TO_SEQNO), which is replaced by the sequence number as soon as that
+// sequence number is known.
+
+#define PAYLOAD_FLD1 0
+#define PAYLOAD_FLD2 1
+#define PAYLOAD_FLD3 2
+
+
+
+class AM_HS;
+
+class temporaryPacket {
+public:
+   temporaryPacket(RLC * rlc):tempPDUTimer(rlc, RLC_TIMER_TEMP_PDU) {
+   } Packet   *p;
+   int         concat_data;
+   UmtsTimer   tempPDUTimer;
+};
+
+class am_flow_information {
+public:
+   am_flow_information(AM_HS * amhs, int flowID):set_poll_(0), seqno_(0),
+         send_status_(0), SDU_size_(0), poll_seq_(0), prohibited_(0), FSN_(-1),
+         b_bal_(0), length_(0), maxseq_(-1), highest_ack_(0), maxseen_(0),
+         next_(0), tx_PDUs_(0), d_address_(0), macDA_(0),
+         poll_timer_((RLC *) amhs, RLC_TIMER_POLL, flowID),
+         stprob_timer_((RLC *) amhs, RLC_TIMER_STPROB, flowID),
+         sinfo_timer_((RLC *) amhs, RLC_TIMER_STATUS, flowID) {
+   } umtsQueue retransmissionBuffer_;
+
+   // We need a separate queue per flow-id.
+
+   vector < umtsQueue * >transmissionBuffer_;
+   // For our Transmission Buffer we use a vector of rlcQueue, for each
+   // flow-id and priority-pair one queue exists.
+
+   int         set_poll_;
+   int         seqno_;
+
+   int         send_status_;
+   int         SDU_size_;       // stores the original size of the SDU when a part already
+
+   // was concatenated
+
+
+   int         poll_seq_;       // stores the highest sequence number of a packet including
+
+   // a poll bit
+   int         prohibited_;
+
+   int         FSN_;            // First Sequence Number of the bitmap
+   int         b_bal_;          // number of 0s in bitmap
+   int         length_;         // length of bitmap
+
+   int         maxseq_;         // highest seqno transmitted so far
+   int         highest_ack_;    // highest ack recieved by sender
+   int         maxseen_;        // max PDU (seqno)number seen by reciever
+   int         seen_[MWS];      // array of PDUs seen by reciever
+   int         next_;           // next PDU expected by receiver
+
+   int         tx_PDUs_;        // Number of PDUs sent after the last poll-bit has been set
+
+   int         d_address_;      // destination address of this RLC Entity
+   int         macDA_;          // mac destination address for packets created by this RLC
+
+   // Entity
+
+   umtsQueue   sduB_;
+
+   UmtsTimer   poll_timer_;
+   UmtsTimer   stprob_timer_;
+   UmtsTimer   sinfo_timer_;
+
+   umtsQueue   rxtB_;
+};
+
+class AM_HS:public RLC_HS {
+public:
+   AM_HS();
+   virtual void recv(Packet *, Handler *);
+   int         command(int, const char *const *);
+   void        credit_update(vector < int >new_rlc_credits);
+   void        timeout(int tno, int flowID = -1);
+protected:
+   void        enqueInBackOfTransmissionBuffer(Packet * p);
+   int         enqueInFrontOfTransmissionBuffer(Packet * p);
+   void        sendDown(Packet * p);
+   void        StoreTemporaryPacket(Packet * p, int concat_data);
+   void        handleTemporaryPacket(Packet * p);
+   void        completePDU(Packet * p);
+   void        insertStatusInformation(Packet * p);
+   void        checkForMissingPDU(Packet * opkt);
+   Packet     *createBitmapAck(int flowID, Packet * p = NULL);
+   void        processBitmapAck(Packet * p);
+   int         StatusPDUSize(int flowID);
+   int         update(int, int, int flowID);
+   void        makeSDU(int numSDU, int flowID);
+
+               vector < am_flow_information * >flowInfo_;
+   // For each flow information has to be kept. All this information is kept in
+   // this struct.
+
+   int         lengthIndicatorSize_;
+   // The size of the Length indicator + the
+   // extention bit. The size is in bytes. The
+   // size is 1 or 2 bytes depending on the size
+   // of the PDUs.
+
+   int         win_;
+   // defines the RLC Window Size, which is the amount of packets that can be
+   // sent after the last acknowledged packet.
+
+   int         flowMax_;
+   // The maximum number of flows
+
+   int         priorityMax_;
+   // The maximum number of priorities
+
+   int         bufferLevelMax_;
+   // The maximum number of PDUs for each flow-id and
+   // priority pair in the Transmission Buffer.
+
+   int         creditAllocationInterval_;
+   // The number of TTIs between a new
+   // credit allocation.
+
+   double      tempPDUTimeOutTime_;
+   // When a PDU is constructed that has some
+   // space left, the PDU is stored in the vector
+   // temporaryPackets_. A timeout will be set
+   // to ensure that when no further SDU arrives
+   // with the same flow-id and priority, the
+   // not-full PDU will be sent and will not
+   // wait indefinitely.
+
+               vector < temporaryPacket * >temporaryPackets_;
+   // In this vector Temporary PDUs are stored. These are PDUs that a not
+   // completely full, and they can be possibly concatenated with a part of
+   // a new SDU. However, this concatenation should be done quick enough,
+   // otherwise timeouts and unnesessary delays may occur. So, a timer will
+   // be set, when the concatenation can be done before the timer times out,
+   // the PDU will be concatenated with a part of a new SDU. When the timer
+   // times out, the Temporary Packet is padded and sent without concatenation.
+
+   UmtsTimer   creditTimer_;
+   // This timer is used for the timout once every
+   // creditAllocationTimeoutInterval_. Then the RLC will start a new credit
+   // allocation.
+
+   double      creditAllocationTimeoutInterval_;
+   // = TTI_ * credit_allocation_interval_
+
+   int         poll_PDU_;       // number of PDUs before a bitmap poll should be sent
+   double      overhead_;       // Time that is needed to contruct SDUs
+   double      poll_timeout_;   // rtt value to be used for timeout to recv status PDU
+   double      stprob_timeout_; // value for the status prohibit timer
+   double      status_timeout_;
+   // Value for the length the status information should be postponed and
+   // tried to be piggybacked before they are forced to be send.
+
+   int         payloadSize_;    // user data per DATA PDU
+   double      TTI_;
+
+   int         ack_pdu_header_;
+   int         status_pdu_header_;
+   int         length_indicator_;
+   int         min_concat_data_;
+
+   int         address_;        // address of this RLC Entity
+
+};
+
+#endif
diff -urN ns-2.30-orig/umts/am.cc ns-2.30-eu112/umts/am.cc
--- ns-2.30-orig/umts/am.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/am.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,1278 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: am.cc,v 1.41 2004/07/01 09:28:30 neill Exp $
+ */
+
+
+#include "am.h"
+#include "mac.h"
+#include "flags.h"
+#include "random.h"
+#include "address.h"
+#include <iostream>
+
+//int hdr_rlc::offset_;
+
+// *INDENT-OFF*
+static class AMRlcClass:public TclClass {
+ public:
+   AMRlcClass():TclClass("UMTS/RLC/AM") {
+   }
+   TclObject *create(int, const char *const *) {
+      return (new AM);
+   }
+} class_am;
+// *INDENT-ON*
+
+AM::AM():RLC(), sent_TTI_PDUs_(0), TTI_PDUs_(0), set_poll_(0), send_ack_(0),
+send_status_(0), SDU_size_(-1), dupacks_(0), rtt_seq_(-1), poll_seq_(-1),
+rtt_active_(0), prohibited_(0), FSN_(-1), b_bal_(0), bitmap_(0), maxseq_(-1),
+t_seqno_(0), highest_ack_(-1), maxseen_(-1), next_(0), tx_PDUs_(0), tx_SDUs_(0),
+rx_PDUs_(0), rx_SDUs_(0), TTI_time_(-1), rtx_timer_(this, RLC_TIMER_RTX),
+poll_timer_((RLC *) this, RLC_TIMER_POLL), delsnd_timer_(this,
+                                                         RLC_TIMER_DELSND),
+stprob_timer_(this, RLC_TIMER_STPROB), tti_timer_(this, RLC_TIMER_TTI)
+{
+   bind("win_", &win_);
+   bind_bw("maxRBSize_", &maxRBSize_);
+   bind("ack_mode_", &ack_mode_);
+   bind("poll_PDU_", &poll_PDU_);
+   bind_time("rtx_timeout_", &rtx_timeout_);
+   bind_time("poll_timeout_", &poll_timeout_);
+   bind_time("overhead_", &overhead_);
+   bind_time("stprob_timeout_", &stprob_timeout_);
+   bind("noFastRetrans_", &noFastRetrans_);
+   bind("numdupacks_", &numdupacks_);
+   bind("payload_", &payload_);
+   bind_bw("bandwidth_", &bandwidth_);
+   bind_time("TTI_", &TTI_);
+   bind("length_indicator_", &length_indicator_);
+   bind("ack_pdu_header_", &ack_pdu_header_);
+   bind("status_pdu_header_", &status_pdu_header_);
+   bind("min_concat_data_", &min_concat_data_);
+   bind_time("max_status_delay_", &max_status_delay_);
+   bind_time("max_ack_delay_", &max_ack_delay_);
+   bind("macDA_", &macDA_);
+   memset(seen_, 0, sizeof(seen_));
+   seqno_ = -1;
+
+}
+
+int AM::command(int argc, const char *const *argv)
+{
+   if (argc == 2) {
+      Tcl & tcl = Tcl::instance();
+      if (strcmp(argv[1], "TTI") == 0) {
+         tcl.resultf("%f", TTI_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "BW") == 0) {
+         tcl.resultf("%f", bandwidth_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "start_TTI") == 0) {
+         tti_timer_.sched(TTI_ - 0.001);
+         TTI_PDUs_ = (int) (bandwidth_ * TTI_) / (payload_ * 8);
+         return TCL_OK;
+      }
+   } else if (argc == 3) {
+      if (strcmp(argv[1], "macDA") == 0) {
+         macDA_ = atoi(argv[2]);
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "addr") == 0) {
+         address_ = Address::instance().str2addr(argv[2]);
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "daddr") == 0) {
+         d_address_ = Address::instance().str2addr(argv[2]);
+         return (TCL_OK);
+      }
+   }
+   return LL::command(argc, argv);
+}
+
+void AM::recv(Packet * p, Handler * h)
+{
+
+   hdr_cmn    *ch = HDR_CMN(p);
+
+
+   /* If direction = UP, then pass it up the stack
+    * Otherwise, set direction to DOWN and pass it down the stack */
+
+   if (ch->direction() == hdr_cmn::UP) {
+
+      hdr_rlc    *llh = hdr_rlc::access(p);
+
+
+      if (llh->dst() != address_ || ch->error() > 0) {
+         Packet::free(p);
+         /* PDUs with errors, or those meant for another UE */
+         return;                /* should have been dropped before this. */
+      }
+
+      assert(chk_size(p));
+      flowID_ = hdr_ip::access(p)->flowid();
+
+      if (llh->lltype() == RLC_ACK) {
+         if (llh->a_seqno() > highest_ack_) {
+            newack(p);
+         } else if (llh->a_seqno() == highest_ack_) {
+            if (++dupacks_ == numdupacks_ && !noFastRetrans_) {
+               reset_rtx_timer();
+            }
+         }
+         Packet::free(p);
+      } else if (llh->lltype() == RLC_BACK) {
+         newback(p);
+         Packet::free(p);
+      } else if (llh->lltype() == RLC_DATA || llh->lltype() == RLC_PB_ACK
+                 || llh->lltype() == RLC_PB_BACK) {
+         if (llh->lltype() == RLC_PB_ACK) {
+            if (llh->a_seqno() > highest_ack_) {
+               newack(p);
+            } else if (llh->a_seqno() == highest_ack_) {
+               if (++dupacks_ == numdupacks_ && !noFastRetrans_) {
+                  reset_rtx_timer();
+               }
+            }
+         } else if (llh->lltype() == RLC_PB_BACK) {
+            newback(p);
+         }
+
+         /* Figure out if any SDUs can be handed up. */
+         int numSDU = update(llh->seqno(), llh->eopno());
+
+
+         ack(p);
+         if (llh->seqno() == llh->eopno() && numSDU >= 0) {
+            sduB_.orderedEnque(p);
+         } else {
+            Packet::free(p);
+         }
+         /* "make" and send up the following SDUs */
+         if (numSDU > 0) {
+            makeSDU(numSDU);
+         }
+      } else {
+         drop(p);               /* Unknown type */
+      }
+      return;
+   }
+   ch->direction() = hdr_cmn::DOWN;
+   sendDown(p);
+}
+
+
+bool AM::chk_size(Packet * p)
+{
+   hdr_rlc    *llh = hdr_rlc::access(p);
+
+
+   int size = 0;
+
+   size += llh->lengthInd_;
+   size += llh->payload_[0];
+   size += llh->payload_[1];
+   size += llh->payload_[2];
+   size += llh->padding_;
+
+   return size == payload_;
+//    if (llh->lengthInd_ == 0) {
+//       size = llh->payload_[0];
+//    } else {
+//       for (int i = 0; i < llh->lengthInd_; i++) {
+//          size = size + ((length_indicator_ + 1) / 8) + llh->payload_[i];
+//       }
+//    }
+//    if ((size + llh->padding_) == payload_) {
+//       return true;
+//    } else {
+//       return false;
+//    }
+}
+
+
+
+void AM::sendDown(Packet * p)
+{
+   if ((rcvB_.size() + hdr_cmn::access(p)->size()) <= maxRBSize_) {
+      rcvB_.enque(p);
+   } else {
+      /* No space in recv buffer for this SDU */
+      drop(p);
+   }
+}
+
+Packet     *AM::makePDU(int PB_bytes)
+{
+   hdr_cmn    *ch;
+   hdr_ip     *iph;
+   hdr_tcp    *tcph;
+   hdr_rlc    *llh;
+   char       *mh;
+
+
+   int available = payload_;
+   int concat_data = 0;
+   int end_PDU = 0;
+   int padding = 0;
+   int force_length_indicator = 0;
+
+   Packet     *c;
+   Packet     *p = rcvB_.dequeCopy();
+
+
+   if (PB_bytes != 0) {
+      available = payload_ - ((length_indicator_ + 1) / 8) - PB_bytes;
+      if (hdr_cmn::access(p)->size() <= available) {
+         end_PDU = 1;
+         concat_data = available - hdr_cmn::access(p)->size()
+               - ((length_indicator_ + 1) / 8);
+         padding = available - hdr_cmn::access(p)->size();
+         /* This amount of padding IF we dont concat. */
+      }
+   } else if (hdr_cmn::access(p)->size() < available) {
+      if (hdr_cmn::access(p)->size() <=
+          available - ((length_indicator_ + 1) / 8)) {
+         end_PDU = 1;
+         concat_data = available - hdr_cmn::access(p)->size()
+               - (2 * ((length_indicator_ + 1) / 8));
+         padding = available - hdr_cmn::access(p)->size()
+               - ((length_indicator_ + 1) / 8);
+      }
+      force_length_indicator = 1;
+   } else if (hdr_cmn::access(p)->size() == available) {
+      end_PDU = 1;
+   }
+   if (concat_data < min_concat_data_ || (rcvB_.size(2) <= concat_data)) {
+      concat_data = 0;
+   } else {
+      padding = 0;
+   }
+   if (end_PDU) {
+      Packet     *temp = rcvB_.deque();
+
+      Packet::free(temp);
+
+      c = p;
+      ch = HDR_CMN(c);
+      llh = hdr_rlc::access(c);
+
+      llh->lptype() = ch->ptype();
+      llh->lerror_ = ch->error();
+      llh->lts_ = ch->timestamp();
+
+      if (SDU_size_ > 0) {
+         llh->lsize_ = SDU_size_;
+      } else {
+         llh->lsize_ = ch->size();
+      }
+
+      SDU_size_ = -1;
+
+      llh->lltype() = RLC_DATA;
+      llh->seqno_ = ++seqno_;
+      llh->eopno_ = llh->seqno_;
+      llh->dst() = d_address_;
+      llh->src() = address_;
+      llh->lengthInd_ = 0;
+
+      if (PB_bytes || concat_data || padding || force_length_indicator) {
+         llh->lengthInd_++;
+      }
+
+      for (int i = 1; i < 3; i++) {
+         llh->payload_[i] = 0;
+      }
+
+      llh->payload_[0] = hdr_cmn::access(c)->size();
+
+      if (concat_data) {
+         llh->lengthInd_++;
+         llh->payload_[1] = concat_data;
+
+         if (PB_bytes != 0) {
+            llh->padding_ = PB_bytes;
+         } else {
+            llh->padding_ = 0;
+         }
+         SDU_size_ = rcvB_.red_size(concat_data);
+      } else if (PB_bytes != 0) {
+         llh->padding_ = PB_bytes + padding;
+      } else {
+         llh->padding_ = padding;
+      }
+      ch->ptype() = PT_AMDA;
+      ch->error() = 0;
+      ch->timestamp() = Scheduler::instance().clock();
+      ch->size() = payload_;
+
+      mh = (char *) c->access(hdr_mac::offset_);
+      struct hdr_mac *dh = (struct hdr_mac *) mh;
+
+      dh->macDA_ = macDA_;
+      dh->macSA_ = -1;
+      dh->hdr_type() = ETHERTYPE_RLC;
+
+   } else {
+      if (SDU_size_ < 0) {
+         SDU_size_ = hdr_cmn::access(p)->size();
+      }
+      c = allocpkt(hdr_cmn::access(p)->uid());
+      ch = HDR_CMN(c);
+      iph = hdr_ip::access(c);
+      tcph = hdr_tcp::access(c);
+      llh = hdr_rlc::access(c);
+      hdr_ip     *piph = hdr_ip::access(p);
+      hdr_tcp    *ptcph = hdr_tcp::access(p);
+      hdr_flags  *phf = hdr_flags::access(p);
+
+      llh->lltype() = RLC_DATA;
+      llh->seqno_ = ++seqno_;
+      llh->eopno_ = -1;
+      llh->dst() = d_address_;
+      llh->src() = address_;
+      llh->padding_ = 0;
+      llh->lengthInd_ = 0;
+
+      if (PB_bytes || force_length_indicator) {
+         llh->lengthInd_++;
+      }
+
+      for (int i = 1; i < 3; i++) {
+         llh->payload_[i] = 0;
+      }
+      if (force_length_indicator) {
+         llh->payload_[0] = payload_ - ((length_indicator_ + 1) / 8);
+      } else if (PB_bytes != 0) {
+         llh->payload_[0] = payload_ - ((length_indicator_ + 1) / 8) - PB_bytes;
+         llh->padding_ = PB_bytes;
+      } else {
+         llh->payload_[0] = payload_;
+      }
+
+      rcvB_.red_size(llh->payload_[0]);
+
+      ch->ptype() = PT_AMDA;
+      ch->size() = payload_;
+
+      iph->flowid() = piph->flowid();
+      iph->saddr() = piph->saddr();
+      iph->sport() = piph->sport();
+      iph->daddr() = piph->daddr();
+      iph->dport() = piph->dport();
+      iph->ttl() = piph->ttl();
+
+      tcph->seqno() = ptcph->seqno();
+
+      hdr_flags  *hf = hdr_flags::access(c);
+
+      hf->ecn_ = phf->ecn_;
+      hf->cong_action_ = phf->cong_action_;
+      hf->ecn_to_echo_ = phf->ecn_to_echo_;
+      hf->fs_ = phf->fs_;
+      hf->ecn_capable_ = phf->ecn_capable_;
+
+      mh = (char *) c->access(hdr_mac::offset_);
+      struct hdr_mac *dh = (struct hdr_mac *) mh;
+
+      dh->macDA_ = macDA_;
+      dh->macSA_ = -1;
+      dh->hdr_type() = ETHERTYPE_RLC;
+   }
+   return c;
+}
+
+
+int AM::PB_S_PDU()
+{
+   int position = 0;
+
+   if ((payload_ - StatusPDUSize() - (2 * ((length_indicator_ + 1) / 8)))
+       < min_concat_data_) {
+      return 0;                 /* Status PDU is too large to piggy back with */
+      /* enough data to meet minimum criteria. */
+   }
+   if (t_seqno_ > highest_ack_ + win_ - b_bal_) {
+      return 0;                 /* Cant send Data PDUs because window is full. */
+      /* Send status with padding immediately. */
+   }
+   
+   //Neill: checking indexing
+
+   for (int i = 1; i <= b_bal_; i++) {
+   //for (int i = 0; i < b_bal_; i++) {
+      Packet     *p = rxtB_.dequeCopy(bRxtSeq(i));
+
+      if (S_Piggybackable(p)) {
+         Packet::free(p);
+         return ++position;
+      }
+      position++;
+      Packet::free(p);
+   }
+
+   if (rcvB_.size() != 0) {
+      return ++position;
+   }
+   return 0;
+}
+
+
+int AM::PB_PA_PDU()
+{
+   int position = 0;
+
+   if (payload_ - AckPDUSize() - (2 * ((length_indicator_ + 1) / 8)) <
+       min_concat_data_) {
+      return 0;
+   } else if (t_seqno_ > highest_ack_ + win_) {
+      return 0;
+   } else if (t_seqno_ <= maxseq_) {
+      for (int i = t_seqno_; i <= maxseq_; i++) {
+         Packet     *p = rxtB_.dequeCopy(i);
+
+         if (PA_Piggybackable(p)) {
+            Packet::free(p);
+            return ++position;
+         }
+         position++;
+         Packet::free(p);
+      }
+   }
+
+   if (rcvB_.size() != 0) {
+      return ++position;
+   }
+   return 0;
+}
+
+
+bool AM::PA_Piggybackable(Packet * p)
+{
+   if (hdr_rlc::access(p)->padding()) {
+      if (hdr_rlc::access(p)->padding() >=
+          (AckPDUSize() + ((length_indicator_ + 1) / 8))) {
+         return true;
+      }
+   }
+   return false;
+}
+
+
+int AM::AckPDUSize()
+{
+   int bytes;
+
+   if (ack_pdu_header_ % 8) {
+      bytes = ack_pdu_header_ / 8 + 1;
+   } else {
+      bytes = ack_pdu_header_ / 8;
+   }
+   return bytes;
+}
+
+
+bool AM::S_Piggybackable(Packet * p)
+{
+   if (hdr_rlc::access(p)->padding()) {
+      if (hdr_rlc::access(p)->padding() >=
+          (StatusPDUSize() + ((length_indicator_ + 1) / 8))) {
+         return true;
+      }
+   }
+   return false;
+}
+
+
+int AM::StatusPDUSize()
+{
+   int first_missing = next_;
+
+   while (seen_[first_missing & MWM]) {
+      ++first_missing;
+   }
+
+   int fsn = first_missing - 1;
+   int bits = maxseen_ - fsn + status_pdu_header_;
+
+   int bytes;
+
+   if (bits % 8) {
+      bytes = bits / 8 + 1;
+   } else {
+      bytes = bits / 8;
+   }
+   return bytes;
+}
+
+
+double AM::send_time(int position)
+{
+   int PDUs_left_in_current_TTI = TTI_PDUs_ - sent_TTI_PDUs_;
+   int i = 0;
+
+   while (1) {
+      if (position <= (i * TTI_PDUs_ + PDUs_left_in_current_TTI)) {
+         return (tti_timer_.timeOfExpiry() + TTI_ * i);
+      }
+      i++;
+   }
+}
+
+
+/*
+ *
+ */
+void AM::send_much(int force)
+{
+   Packet     *p = NULL;
+
+   if (!force && delsnd_timer_.status() == TIMER_PENDING) {
+      return;
+   }
+
+   while (((t_seqno_ <= highest_ack_ + win_ - b_bal_)
+           || set_poll_ || send_status_ || send_ack_)) {
+
+      if ((rcvB_.size() == 0) && (b_bal_ == 0)
+          && (!set_poll_) && (!send_status_)
+          && (!send_ack_) && (t_seqno_ > maxseq_)) {
+         sent_TTI_PDUs_ = 0;
+         return;
+         /* There are no new PDUs to send or retransmitt */
+      } else if (sent_TTI_PDUs_ == TTI_PDUs_) {
+         sent_TTI_PDUs_ = 0;
+         return;
+      }
+
+      if (overhead_ == 0 || force) {
+         if (send_status_) {
+            int position = PB_S_PDU();
+
+            if (position && ((send_time(position) - earliest_status_send_)
+                             <= max_status_delay_)) {
+               /* DO nothing. The Status report 
+                * will be piggybacked later. */
+            } else {
+               Packet     *pkt = make_bitmap_ack(NULL);
+
+               sent_TTI_PDUs_++;
+               send_status_ = 0;
+               set_status_prohibit_timer();
+               downtarget_->recv(pkt);
+               delsnd_timer_.resched(Random::uniform(overhead_));
+               return;
+            }
+         } else if (send_ack_) {
+            int position = PB_PA_PDU();
+
+            if (position && ((send_time(position) - earliest_ack_send_)
+                             <= max_ack_delay_)) {
+               /* DO nothing. The ack will be piggybacked later. */
+            } else {
+               Packet     *pkt = make_positive_ack(NULL);
+
+               sent_TTI_PDUs_++;
+               send_ack_ = 0;
+               downtarget_->recv(pkt);
+               delsnd_timer_.resched(Random::uniform(overhead_));
+               return;
+            }
+         }
+
+         int force_set_rtx_timer = 0;
+
+         if (set_poll_ && (rcvB_.size() == 0) && (b_bal_ == 0)) {
+            p = rxtB_.dequeTailCopy();
+            if (send_status_ && S_Piggybackable(p)) {
+               make_bitmap_ack(p);
+               set_status_prohibit_timer();
+               send_status_ = 0;
+            }
+         } else if (b_bal_ != 0) {
+            int temp_val = bRxtSeq(0);
+
+            
+            p = rxtB_.dequeCopy(temp_val); //side-effect: b_bal_--
+            if (send_status_ && S_Piggybackable(p)) {
+               make_bitmap_ack(p);
+               set_status_prohibit_timer();
+               send_status_ = 0;
+            }
+            // for last PDU to be re-transmitted be sure 
+            // to trigger polling function
+            if (b_bal_ == 0) {
+               set_poll_ = 1;
+            }
+         } else if (t_seqno_ > maxseq_) {
+            // for bitmap this is always true
+            if (send_status_) {
+               p = makePDU(StatusPDUSize()
+                           + ((length_indicator_ + 1) / 8));
+            } else if (send_ack_) {
+               p = makePDU(AckPDUSize()
+                           + ((length_indicator_ + 1) / 8));
+            } else {
+               p = makePDU(0);
+            }
+
+            rxtB_.enque(p->copy());
+
+            if (send_status_) {
+               make_bitmap_ack(p);
+               set_status_prohibit_timer();
+               send_status_ = 0;
+            } else if (send_ack_) {
+               make_positive_ack(p);
+               send_ack_ = 0;
+            }
+
+            assert(t_seqno_ == hdr_rlc::access(p)->seqno());
+
+            // for last PDU in rcv buffer, 
+            // be sure to trigger polling function
+            if (rcvB_.size() == 0) {
+               set_poll_ = 1;
+            }
+            if (highest_ack_ == maxseq_) {
+               force_set_rtx_timer = 1;
+            }
+            maxseq_ = t_seqno_;
+            t_seqno_++;
+         } else {
+            p = rxtB_.dequeCopy(t_seqno_);
+            if (send_ack_ && PA_Piggybackable(p)) {
+               make_positive_ack(p);
+               send_ack_ = 0;
+            }
+            t_seqno_++;
+         }
+
+          assert(p);
+         ++tx_PDUs_;
+
+         if (ack_mode_ == 1) {
+            set_poll_ = 0;
+            if (!rtt_active_) {
+               rtt_active_ = 1;
+               if (t_seqno_ > rtt_seq_) {
+                  rtt_seq_ = t_seqno_;
+               }
+            }
+            if (!(rtx_timer_.status() == TIMER_PENDING)
+                || force_set_rtx_timer) {
+               set_rtx_timer();
+               /* No timer pending.  Schedule one. */
+            }
+         } else if (ack_mode_ == 2) {
+            if (!(tx_PDUs_ % poll_PDU_) || set_poll_) {
+               hdr_rlc::access(p)->poll() = true;
+               if ((hdr_rlc::access(p)->seqno() >= poll_seq_)
+                   || (poll_timer_.status() != TIMER_PENDING)) {
+                  poll_seq_ = hdr_rlc::access(p)->seqno();
+                  set_poll_timer();
+               }
+               tx_PDUs_ = 0;
+            }
+         }
+         set_poll_ = 0;
+
+         sent_TTI_PDUs_++;
+         downtarget_->recv(p);
+         delsnd_timer_.resched(Random::uniform(overhead_));
+         return;
+      } else if (!(delsnd_timer_.status() == TIMER_PENDING)) {
+         /*
+          * Set a delayed send timeout.
+          */
+         delsnd_timer_.resched(Random::uniform(overhead_));
+         return;
+      }
+
+   }
+   sent_TTI_PDUs_ = 0;
+}
+
+
+/*
+ * returns number of SDUs that can be "delivered" to the Agent
+ * also updates the receive window (i.e. next_, maxseen, and seen_ array)
+ */
+int AM::update(int seq, int eopno)
+{
+   int numSDU = 0;
+   bool just_marked_as_seen = FALSE;
+
+   // start by assuming the segment hasn't been received before
+
+   if (seq - next_ >= MWM) {
+      // next_ is next PDU expected; MWM is the maximum
+      // window size minus 1; if somehow the seqno of the
+      // PDU is greater than the one we're expecting+MWM,
+      // then ignore it.
+      return -1;
+   }
+
+   if (seq > maxseen_) {
+      // the PDU is the highest one we've seen so far
+      int i;
+
+      for (i = maxseen_ + 1; i < seq; ++i) {
+         seen_[i & MWM] = 0;
+      }
+      // we record the PDUs between the old maximum and
+      // the new max as being "unseen" i.e. 0
+      maxseen_ = seq;
+      if (seq == eopno) {
+         seen_[maxseen_ & MWM] = 1;
+      } else {
+         seen_[maxseen_ & MWM] = 2;
+      }
+      // set this PDU as being "seen".
+      seen_[(maxseen_ + 1) & MWM] = 0;
+      // clear the array entry for the PDU immediately
+      // after this one
+      just_marked_as_seen = TRUE;
+      // necessary so this PDU isn't confused as being a duplicate
+   }
+   int next = next_;
+
+   if (seq < next) {
+      // Duplicate PDU case 1: the PDU is to the left edge of
+      // the receive window; therefore we must have seen it
+      // before
+      return -1;
+   }
+
+   if (seq >= next && seq <= maxseen_) {
+      // next is the left edge of the recv window; maxseen_
+      // is the right edge; execute this block if there are
+      // missing PDUs in the recv window AND if current
+      // PDU falls within those gaps
+
+      if (seen_[seq & MWM] && !just_marked_as_seen) {
+         // Duplicate case 2: the segment has already been
+         // recorded as being received (AND not because we just
+         // marked it as such)
+         return -1;
+      }
+      if (seq == eopno) {
+         seen_[seq & MWM] = 1;
+      } else {
+         seen_[seq & MWM] = 2;
+      }
+      // record the PDU as being seen
+
+      while (seen_[next & MWM]) {
+         // This loop sees if any SDUs can now be deliver to
+         // the Agent due to this PDU arriving
+         next++;
+         if ((seen_[(next - 1) & MWM] == 1)) {
+            next_ = next;
+            // store the new left edge of the window
+            numSDU++;
+         }
+      }
+   }
+   return numSDU;
+}
+
+
+/*
+ * Process an Positive ACK of previously unacknowleged data.
+ */
+void AM::newack(Packet * pkt)
+{
+   hdr_rlc    *llh = hdr_rlc::access(pkt);
+
+   dupacks_ = 0;
+   highest_ack_ = llh->a_seqno();
+
+   /* delete all the Acked PDUs from RXT Buff i.e. PDUs till highest_ack_ */
+   rxtB_.dropTill(highest_ack_);
+
+   if (t_seqno_ < highest_ack_ + 1) {
+      t_seqno_ = highest_ack_ + 1;
+   }
+   if (rtt_active_ && llh->a_seqno() >= rtt_seq_) {
+      rtt_active_ = 0;
+   }
+   /* Set new retransmission timer if not all outstanding data acked.
+    * Otherwise, if a timer is still outstanding, cancel it. */
+   if (llh->a_seqno() < maxseq_) {
+      set_rtx_timer();
+   } else {
+      cancel_rtx_timer();
+   }
+}
+
+
+/*
+ * Process a Bitmap ACK.
+ */
+void AM::newback(Packet * pkt)
+{
+   hdr_rlc    *llh = hdr_rlc::access(pkt);
+
+   b_bal_ = 0;
+   length_ = llh->length();
+   FSN_ = llh->FSN();
+
+
+   rxtB_.dropTill(FSN_);
+
+   if (bitmap_) {
+      delete[]bitmap_;
+   }
+   bitmap_ = new int[length_];
+
+   for (int i = 0; i < length_; i++) {
+      bitmap_[i] = llh->bitmap(i);
+      if (bitmap_[i] == 0) {
+         b_bal_++;
+      } else {
+         Packet     *r = rxtB_.deque(FSN_ + i);
+
+         if (r) {
+            Packet::free(r);
+         }
+      }
+   }
+   delete[]llh->bitmap_;
+
+   highest_ack_ = FSN_ + length_ - 1;
+   assert(t_seqno_ > highest_ack_);
+   if (highest_ack_ >= poll_seq_) {
+      cancel_poll_timer();
+      poll_seq_ = -1;
+      set_poll_ = 0;
+   }
+}
+
+int AM::bRxtSeq(int position)
+{
+
+
+
+   int counter = 0;
+
+   if (position == 0) {
+      b_bal_--;
+   }
+   for (int i = 0; i < length_; i++) {
+      if (bitmap_[i] == 0) {
+         counter++;
+         if (position == 0) {
+            bitmap_[i] = 1;
+            // Neill(16/07/04): Increment of 1 seems to be wrong here
+            // return (i + FSN_ + 1);
+            return (i + FSN_);
+         } else if (counter == position) {
+           // return (i + FSN_ + 1);
+            return (i + FSN_);
+         }
+      }
+   }
+   return -1;
+}
+
+
+void AM::ack(Packet * opkt)
+{
+   int first_missing = next_;
+
+   while (seen_[first_missing & MWM]) {
+      ++first_missing;
+   }
+   if (ack_mode_ == 1) {
+      /* Do you want to set a timer so you dont send an ack every PDU? */
+      if (send_ack_ == 1) {
+         /* Do nothing since an ack is already pending. */
+      } else {
+         if (delsnd_timer_.status() == TIMER_PENDING
+             && sent_TTI_PDUs_ < TTI_PDUs_) {
+            earliest_ack_send_ = tti_timer_.timeOfExpiry();
+         } else {
+            earliest_ack_send_ = tti_timer_.timeOfExpiry() + TTI_;
+         }
+         send_ack_ = 1;
+      }
+   } else if (ack_mode_ == 2) {
+      if (prohibited_) {
+         return;
+      }
+      /* opkt is the "old" PDU that was received */
+
+      if (stprob_timer_.status() == TIMER_PENDING) {
+         if (hdr_rlc::access(opkt)->poll()) {
+            prohibited_ = 1;
+         }
+         return;
+      }
+
+      if (first_missing < maxseen_ || hdr_rlc::access(opkt)->poll()) {
+         if (send_status_ == 1) {
+            /* Do nothing since a status report is already pending. */
+         } else {
+            if (delsnd_timer_.status()
+                == TIMER_PENDING && sent_TTI_PDUs_ < TTI_PDUs_) {
+               earliest_status_send_ = tti_timer_.timeOfExpiry();
+            } else {
+               earliest_status_send_ = tti_timer_.timeOfExpiry() + TTI_;
+            }
+            send_status_ = 1;
+         }
+      }
+   }
+}
+
+
+Packet     *AM::make_positive_ack(Packet * p)
+{
+   Packet     *npkt;
+   hdr_rlc    *nrlc;
+   hdr_cmn    *nch;
+
+   int first_missing = next_;
+
+   while (seen_[first_missing & MWM]) {
+      ++first_missing;
+   }
+
+   if (p == NULL) {
+      npkt = allocpkt(0);
+      nrlc = hdr_rlc::access(npkt);
+      nch = hdr_cmn::access(npkt);
+      hdr_ip     *niph = hdr_ip::access(npkt);
+      hdr_tcp    *ntcp = hdr_tcp::access(npkt);
+
+      nrlc->lltype() = RLC_ACK;
+      nrlc->dst() = d_address_;
+      nrlc->src() = address_;
+      nrlc->a_seqno() = first_missing - 1;   /* cumulative sequence number */
+      nrlc->seqno() = nrlc->a_seqno(); /* For trace plotting. */
+      nrlc->lengthInd_ = 0;
+      nrlc->padding_ = payload_ - AckPDUSize();
+
+      for (int i = 1; i < 3; i++) {
+         nrlc->payload_[i] = 0;
+      }
+
+      nrlc->payload_[0] = AckPDUSize();
+
+
+      nch->ptype() = PT_AMPA;
+      nch->size() = payload_;
+
+      niph->flowid() = -1;
+      niph->saddr() = -1;
+      niph->sport() = -1;
+      niph->daddr() = -1;
+      niph->dport() = -1;
+      niph->ttl() = 32;
+
+      ntcp->seqno() = -1;
+
+      char       *mh = (char *) npkt->access(hdr_mac::offset_);
+      struct hdr_mac *dh = (struct hdr_mac *) mh;
+
+      dh->macDA_ = macDA_;
+      dh->macSA_ = -1;
+      dh->hdr_type() = ETHERTYPE_RLC;
+
+      return npkt;
+   }
+   npkt = p;
+
+   nrlc = hdr_rlc::access(npkt);
+   nch = hdr_cmn::access(npkt);
+
+   nrlc->lengthInd_++;
+   nrlc->padding_ = nrlc->padding_ - AckPDUSize()
+         - ((length_indicator_ + 1) / 8);
+   nrlc->payload_[nrlc->lengthInd_ - 1] = AckPDUSize();
+
+   nrlc->a_seqno() = first_missing - 1;   /* cumulative sequence number */
+   nrlc->lltype() = RLC_PB_ACK;
+
+   nch->size() = payload_;
+   nch->ptype() = PT_AMPBPA;
+
+   return npkt;
+}
+
+
+Packet     *AM::make_bitmap_ack(Packet * p)
+{
+   Packet     *npkt;
+   hdr_rlc    *nllh;
+   hdr_cmn    *nch;
+
+   int first_missing = next_;
+
+   while (seen_[first_missing & MWM]) {
+      ++first_missing;
+   }
+
+
+   int fsn = first_missing - 1;
+
+   if (fsn < 0) {
+      // When the first packet ever gets a nack we shouldn't try to ack
+      // everything until then.
+      fsn = 0;
+   }
+
+   if (p == NULL) {
+      npkt = allocpkt(0);
+
+      nllh = hdr_rlc::access(npkt);
+      nch = hdr_cmn::access(npkt);
+      hdr_ip     *niph = hdr_ip::access(npkt);
+      hdr_tcp    *ntcp = hdr_tcp::access(npkt);
+      char       *mh = (char *) npkt->access(hdr_mac::offset_);
+
+      nllh->lltype() = RLC_BACK;
+      nllh->dst() = d_address_;
+      nllh->src() = address_;
+      nllh->seqno() = fsn;
+      nllh->lengthInd_ = 0;
+      nllh->padding_ = payload_ - StatusPDUSize();
+
+      for (int i = 1; i < 3; i++) {
+         nllh->payload_[i] = 0;
+      }
+
+      nllh->payload_[0] = StatusPDUSize();
+
+      niph->flowid() = flowID_;
+      niph->saddr() = -1;
+      niph->sport() = -1;
+      niph->daddr() = -1;
+      niph->dport() = -1;
+      niph->ttl() = 32;
+
+      ntcp->seqno() = -1;
+
+      nch->ptype() = PT_AMBA;
+      nch->size() = payload_;
+
+      struct hdr_mac *dh = (struct hdr_mac *) mh;
+
+      dh->macDA_ = macDA_;
+      dh->macSA_ = -1;
+      dh->hdr_type() = ETHERTYPE_RLC;
+   } else {
+      npkt = p;
+      nllh = hdr_rlc::access(npkt);
+      nch = hdr_cmn::access(npkt);
+
+      nllh->lengthInd_++;
+      nllh->padding_ = nllh->padding_ - StatusPDUSize()
+            - ((length_indicator_ + 1) / 8);
+      nllh->payload_[nllh->lengthInd_ - 1] = StatusPDUSize();
+
+      nllh->lltype() = RLC_PB_BACK;
+      nch->ptype() = PT_AMPBBA;
+   }
+
+   nllh->FSN() = fsn;
+   if ((maxseen_ - fsn + 1) > (payload_ * 8 - status_pdu_header_)) {
+      nllh->length() = payload_ * 8 - status_pdu_header_;
+   } else {
+      nllh->length() = maxseen_ - fsn + 1;
+   }
+
+
+   nllh->bitmap_ = new int[nllh->length()];
+
+   for (int i = 0; i < nllh->length(); i++) {
+      seen_[(fsn + i) & MWM]
+            ? nllh->bitmap(i) = 1 : nllh->bitmap(i) = 0;
+   }
+
+   return npkt;
+}
+
+
+/*
+ * allocate a PDU and fill in required fields
+ */
+Packet     *AM::allocpkt(int uid)
+{
+   Packet     *p = Packet::alloc();
+   hdr_cmn    *ch = hdr_cmn::access(p);
+
+/*	ch->ptype() = PT_AMDA; */
+   ch->uid() = uid;
+   ch->error() = 0;
+   ch->timestamp() = Scheduler::instance().clock();
+   ch->iface() = UNKN_IFACE.value();
+   ch->direction() = hdr_cmn::DOWN;
+   //ch->ref_count() = 0;
+
+   return (p);
+}
+
+
+void AM::makeSDU(int numSDU)
+{
+
+   Packet     *p;
+   hdr_cmn    *ch;
+   hdr_rlc    *llh;
+
+   for (int i = 0; i < numSDU; i++) {
+      p = sduB_.deque();
+      assert(p);
+      ch = HDR_CMN(p);
+      llh = hdr_rlc::access(p);
+
+      ch->ptype() = llh->lptype();
+      ch->error() = llh->lerror();
+      ch->timestamp() = llh->lts();
+      ch->size() = llh->lsize();
+
+      uptarget_ ? sendUp(p) : Packet::free(p);
+   }
+}
+
+void AM::CSwitch(double bandwidth, double TTI)
+{
+   bandwidth_ = bandwidth;
+   TTI_ = TTI;
+}
+
+/* 
+ * Process timeout events.
+ */
+void AM::timeout(int tno, int flowID)
+{
+   /* retransmit timer */
+   if (tno == RLC_TIMER_POLL) {
+      if (maxseq_ == FSN_ && b_bal_ == 0) {
+         /*
+          * If no outstanding data, then don't do anything.  
+          */
+         return;
+      }
+      poll_seq_ = -1;
+      set_poll_ = 1;
+   } else if (tno == RLC_TIMER_RTX) {
+      if (highest_ack_ == maxseq_) {
+         /*
+          * If no outstanding data, then don't do anything.  
+          */
+         return;
+      }
+      reset_rtx_timer();
+   } else if (tno == RLC_TIMER_STPROB) {
+      if (prohibited_) {
+         send_status_ = 1;
+         prohibited_ = 0;
+         if (delsnd_timer_.status() == TIMER_PENDING
+             && sent_TTI_PDUs_ < TTI_PDUs_) {
+            earliest_status_send_ = tti_timer_.timeOfExpiry();
+         } else {
+            earliest_status_send_ = tti_timer_.timeOfExpiry() + TTI_;
+         }
+      }
+   } else if (tno == RLC_TIMER_DELSND) {
+      send_much(1);
+   } else if (tno == RLC_TIMER_TTI) {
+      TTI_time_ = Scheduler::instance().clock();
+      TTI_PDUs_ = (int) (bandwidth_ * TTI_) / (payload_ * 8);
+      tti_timer_.resched(TTI_);
+      send_much(0);
+   }
+}
+
+
+/*
+ * Set retransmit timer using current provided rtt estimate.  By calling  
+ * resched(),it does not matter whether the timer was already running.
+ */
+void AM::set_rtx_timer()
+{
+   rtx_timer_.resched(rtx_timeout_);
+}
+
+
+/*
+ * We got a timeout or too many duplicate acks.  Clear the retransmit timer.
+ * Resume the sequence one past the last packet acked.
+ */
+void AM::reset_rtx_timer()
+{
+   cancel_rtx_timer();
+   t_seqno_ = highest_ack_ + 1;
+   rtt_active_ = 0;
+}
+
+
+void AM::cancel_rtx_timer()
+{
+   rtx_timer_.force_cancel();
+}
+
+
+void AM::set_poll_timer()
+{
+   poll_timer_.resched(poll_timeout_);
+}
+
+
+void AM::cancel_poll_timer()
+{
+   poll_timer_.force_cancel();
+}
+
+
+void AM::set_status_prohibit_timer()
+{
+   stprob_timer_.resched(stprob_timeout_ -
+                         (Scheduler::instance().clock() - TTI_time_)
+         );
+}
+
+
+int AM::buff_size()
+{
+   return (rcvB_.size() + rxtB_.size());
+}
+
diff -urN ns-2.30-orig/umts/am.h ns-2.30-eu112/umts/am.h
--- ns-2.30-orig/umts/am.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/am.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: am.h,v 1.14 2004/01/21 15:55:12 wtdavid Exp $
+ */
+
+
+#ifndef ns_am_h
+#define ns_am_h
+
+#include "rlc.h"
+#include "um.h"
+#include "umts-timers.h"
+#include "umts-queue.h"
+
+
+#define MWS 4096             // max window size */
+#define MWM (MWS-1)          // The "win_" parameter, representing the RLC window,
+                     // should be less than equal to MWM.
+
+
+class AM;
+
+class AM:   public RLC {
+
+public:
+   AM();
+   int         buff_size();
+   void        timeout(int tno, int flowID = -1);
+   void        CSwitch(double, double);
+   int        &addr() {
+      return (address_);
+   } int      &daddr() {
+      return (d_address_);
+   }
+   virtual void recv(Packet *, Handler *);
+
+ protected:
+   int         bRxtSeq(int);
+   void        ack(Packet *);
+   Packet     *make_bitmap_ack(Packet *);
+   Packet     *make_positive_ack(Packet *);
+   void        newack(Packet *);
+   void        makeSDU(int);
+   void        send_much(int);
+   void        newback(Packet *);
+   Packet     *allocpkt(int);
+   void        sendDown(Packet *);
+   int         update(int, int);
+   int         command(int, const char *const *);
+
+   bool        chk_size(Packet *);
+   Packet     *makePDU(int);
+   int         PB_S_PDU();
+   int         PB_PA_PDU();
+   bool        PA_Piggybackable(Packet *);
+   int         AckPDUSize();
+   bool        S_Piggybackable(Packet *);
+   int         StatusPDUSize();
+   double      send_time(int);
+
+   void        set_rtx_timer();
+   void        set_poll_timer();
+   void        reset_rtx_timer();
+   void        cancel_rtx_timer();
+   void        cancel_poll_timer();
+   void        set_status_prohibit_timer();
+
+   int         win_;            // RLC window size
+   double      maxRBSize_;      // max length of the recieve buffer
+   int         ack_mode_;       // ack option. Selective repeat or Bitmap
+   int         poll_PDU_;       // number of PDUs before a bitmap poll should be sent
+   double      overhead_;       // Time that is needed to contruct SDUs
+   double      rtx_timeout_;
+   double      poll_timeout_;   // rtt value to be used for timeout to recv status PDU
+   double      stprob_timeout_; // value for the status prohibit timer
+   int         noFastRetrans_;  // No Fast Retransmit option
+   int         numdupacks_;     // dup ACKs before fast retransmit
+
+   int         payload_;        // user data per DATA PDU
+   double      bandwidth_;
+   double      TTI_;
+   double      next_TTI_;
+
+   int         ack_pdu_header_;
+   int         status_pdu_header_;
+   int         length_indicator_;
+   int         min_concat_data_;
+   double      max_status_delay_;
+   double      max_ack_delay_;
+
+   int         sent_TTI_PDUs_;
+   int         TTI_PDUs_;
+   double      earliest_status_send_;
+   double      earliest_ack_send_;
+   int         set_poll_;
+   int         send_ack_;
+   int         send_status_;
+   int         SDU_size_;       // stores the original size of the SDU when a part already
+
+   // was concatenated
+
+
+   int         dupacks_;        // number of (pos) duplicate acks
+   int         rtt_seq_;
+   int         poll_seq_;       // stores the highest sequence number of a packet including
+
+   // a poll bit
+   int         rtt_active_;
+   int         prohibited_;
+
+   int         FSN_;            // First Sequence Number of the bitmap
+   int         b_bal_;          // number of 0s in bitmap (number of nacks in bitmap)
+   int         length_;         // length of bitmap
+   int        *bitmap_;
+
+   int         maxseq_;         // highest seqno transmitted so far
+   int         t_seqno_;        // Seqno of next PDU to be transmitted
+   int         highest_ack_;    // highest ack received by sender
+   int         maxseen_;        // max PDU (seqno)number seen by receiver
+   int         seen_[MWS];      // array of PDUs seen by reciever
+   int         next_;           // next PDU expected by reciever
+
+   int         tx_PDUs_;
+   int         tx_SDUs_;
+   int         rx_PDUs_;
+   int         rx_SDUs_;
+
+   int         address_;        // address of this RLC Entity
+   int         d_address_;      // destination address of this RLC Entity
+
+   double      TTI_time_;
+
+   UmtsTimer   rtx_timer_;
+   UmtsTimer   poll_timer_;
+   UmtsTimer   delsnd_timer_;
+   UmtsTimer   stprob_timer_;
+   UmtsTimer   tti_timer_;
+
+   umtsQueue   rcvB_;
+   umtsQueue   rxtB_;
+   umtsQueue   sduB_;
+
+   int         flowID_;         // The flow-id of the incoming packets, is used to set the
+
+   // flow-id of outgoing packets.
+
+};
+
+#endif
diff -urN ns-2.30-orig/umts/classifier-sport.cc ns-2.30-eu112/umts/classifier-sport.cc
--- ns-2.30-orig/umts/classifier-sport.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/classifier-sport.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: classifier-sport.cc,v 1.3 2004/01/20 13:29:24 simon Exp $
+ */
+
+#include "classifier-sport.h"
+
+SPortClassifier::SPortClassifier():Classifier()
+{
+}
+
+static class SPortClassifierClass:public TclClass {
+public:
+   SPortClassifierClass():TclClass("Classifier/SrcPort") {
+   } TclObject *create(int, const char *const *) {
+      return (new SPortClassifier());
+   }
+}
+
+class_sport_classifier;
+
+int SPortClassifier::classify(Packet * p)
+{
+   // Port classifier returns the source port.
+   hdr_ip     *iph = hdr_ip::access(p);
+
+   return iph->sport();
+};
+
+int SPortClassifier::command(int argc, const char *const *argv)
+{
+   return (Classifier::command(argc, argv));
+}
diff -urN ns-2.30-orig/umts/classifier-sport.h ns-2.30-eu112/umts/classifier-sport.h
--- ns-2.30-orig/umts/classifier-sport.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/classifier-sport.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: classifier-sport.h,v 1.3 2004/01/20 13:29:24 simon Exp $
+ */
+
+#ifndef ns_classifier_sport_h
+#define ns_classifier_sport_h
+
+#include "packet.h"
+#include "ip.h"
+#include "classifier.h"
+
+class SPortClassifier:public Classifier {
+public:
+   SPortClassifier();
+   int         command(int argc, const char *const *argv);
+protected:
+   int         classify(Packet * p);
+};
+
+#endif
diff -urN ns-2.30-orig/umts/cqi.h ns-2.30-eu112/umts/cqi.h
--- ns-2.30-orig/umts/cqi.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/cqi.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: cqi.h,v 1.2 2004/01/20 13:29:24 simon Exp $
+ */
+
+// CQI to Transport Block Size mappings
+// for UE categories 1-6
+// 3GPP TS 25.214 V5.5.0, page 39
+
+#ifndef ns_cqi
+#define ns_cqi
+
+int         cqiMapping[31] = {
+
+   0,                           // 0 (dummy)
+   137,                         // 1
+   173,                         // 2
+   233,                         // 3
+   317,                         // 4
+   377,                         // 5
+   461,                         // 6
+   650,                         // 7
+   792,                         // 8
+   931,                         // 9
+   1262,                        // 10
+   1483,                        // 11
+   1742,                        // 12
+   2279,                        // 13
+   2583,                        // 14
+   3319,                        // 15
+   3565,                        // 16
+   4189,                        // 17
+   4664,                        // 18
+   5287,                        // 19
+   5887,                        // 20
+   6554,                        // 21
+   7168,                        // 22
+   7168,                        // 23
+   7168,                        // 24
+   7168,                        // 25
+   7168,                        // 26
+   7168,                        // 27
+   7168,                        // 28
+   7168,                        // 29
+   7168                         // 30
+};
+
+
+// for UE categories 7-8 (not used)
+
+/*
+9719,  // 23
+11418, // 24
+14411, // 25
+14411, // 26
+14411, // 27
+14411, // 28
+14411, // 29
+14411  // 30
+*/
+
+
+// for UE category 9 (not used)
+
+/*
+17300, // 26
+17300, // 27
+17300, // 28
+17300, // 29
+17300  // 30
+*/
+
+
+// for UE category 10 (not used)
+
+/*
+21754, // 27
+23370, // 28
+24222, // 29
+25558  // 30
+*/
+
+#endif
diff -urN ns-2.30-orig/umts/demuxer.cc ns-2.30-eu112/umts/demuxer.cc
--- ns-2.30-orig/umts/demuxer.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/demuxer.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: demuxer.cc,v 1.4 2004/01/20 13:29:24 simon Exp $
+ */
+
+#include "demuxer.h"
+#include "packet.h"
+
+static class DemuxerClass:public TclClass {
+public:
+   DemuxerClass():TclClass("Demuxer") {
+   } TclObject *create(int, const char *const *) {
+      return (new Demuxer);
+   }
+}
+
+class_Demuxer;
+
+int Demuxer::command(int argc, const char *const *argv)
+{
+   return (BiConnector::command(argc, argv));
+}
+
+void Demuxer::recv(Packet * p, Handler * h)
+{
+   hdr_cmn    *ch = HDR_CMN(p);
+
+   if (ch->ptype() == PT_AMDA || ch->ptype() == PT_AMPA
+       || ch->ptype() == PT_AMBA || ch->ptype() == PT_UM
+       || ch->ptype() == PT_AMPBBA || ch->ptype() == PT_AMPBPA) {
+      downtarget_ ? sendDown(p, h) : drop(p);
+   } else {
+      uptarget_ ? sendUp(p, h) : drop(p);
+   }
+}
diff -urN ns-2.30-orig/umts/demuxer.h ns-2.30-eu112/umts/demuxer.h
--- ns-2.30-orig/umts/demuxer.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/demuxer.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: demuxer.h,v 1.4 2004/01/20 13:29:24 simon Exp $
+ */
+
+
+/* 
+ * Demultiplexes RLC and IP packets at node entry
+ */
+
+#include "bi-connector.h"
+
+class Demuxer:public BiConnector {
+public:
+   Demuxer():BiConnector() {
+   } int       command(int argc, const char *const *argv);
+   void        recv(Packet *, Handler * callback = 0);
+};
diff -urN ns-2.30-orig/umts/demuxerRtModule.cc ns-2.30-eu112/umts/demuxerRtModule.cc
--- ns-2.30-orig/umts/demuxerRtModule.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/demuxerRtModule.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: demuxerRtModule.cc,v 1.3 2004/01/20 13:29:24 simon Exp $
+ */
+
+#include "node.h"
+#include "demuxerRtModule.h"
+
+static class DemuxerRoutingModuleClass:public TclClass {
+public:
+   DemuxerRoutingModuleClass():TclClass("RtModule/Demuxer") {
+   } TclObject *create(int, const char *const *) {
+      return (new DemuxerRoutingModule);
+   }
+}
+
+class_demuxer_routing_module;
+
+int DemuxerRoutingModule::command(int argc, const char *const *argv)
+{
+   Tcl & tcl = Tcl::instance();
+   if (argc == 3) {
+      if (strcmp(argv[1], "route-notify") == 0) {
+         Node       *node = (Node *) (TclObject::lookup(argv[2]));
+
+         if (node == NULL) {
+            tcl.add_errorf("Invalid node object %s", argv[2]);
+            return TCL_ERROR;
+         }
+         if (node != n_) {
+            tcl.add_errorf("Node object %s different from n_", argv[2]);
+            return TCL_ERROR;
+         }
+         n_->route_notify(this);
+         return TCL_OK;
+      }
+      if (strcmp(argv[1], "unreg-route-notify") == 0) {
+         Node       *node = (Node *) (TclObject::lookup(argv[2]));
+
+         if (node == NULL) {
+            tcl.add_errorf("Invalid node object %s", argv[2]);
+            return TCL_ERROR;
+         }
+         if (node != n_) {
+            tcl.add_errorf("Node object %s different from n_", argv[2]);
+            return TCL_ERROR;
+         }
+         n_->unreg_route_notify(this);
+         return TCL_OK;
+      }
+   }
+   return (RoutingModule::command(argc, argv));
+}
diff -urN ns-2.30-orig/umts/demuxerRtModule.h ns-2.30-eu112/umts/demuxerRtModule.h
--- ns-2.30-orig/umts/demuxerRtModule.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/demuxerRtModule.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: demuxerRtModule.h,v 1.3 2004/01/20 13:29:24 simon Exp $
+ */
+
+#ifndef ns_DemuxerRoutingModule_h
+#define ns_DemuxerRoutingModule_h
+
+#include <rtmodule.h>
+
+class DemuxerRoutingModule:public RoutingModule {
+public:
+   DemuxerRoutingModule():RoutingModule() {
+   } virtual const char *module_name() const {
+      return "Demuxer";
+   } virtual int command(int argc, const char *const *argv);
+};
+
+#endif
diff -urN ns-2.30-orig/umts/dummy_drop_tail.cc ns-2.30-eu112/umts/dummy_drop_tail.cc
--- ns-2.30-orig/umts/dummy_drop_tail.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/dummy_drop_tail.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: dummy_drop_tail.cc,v 1.2 2004/01/20 13:29:24 simon Exp $
+ */
+
+#include "dummy_drop_tail.h"
+
+// The only reason why this class exists is because
+//
+// $ns setup-Iub $bs $rnc 622Mbit 622Mbit 0.2ms 0.2ms DropTail 200000
+//
+// doesn't create a queue that holds more than 50 packets. For some reason the
+// last parameter doesn't seem to have any influence. DummyDropTail doesn't
+// have a maximum size, so an enque will always succeed.
+//
+// This large buffer is needed because AM-hs will send large bursts of packets
+// to the MAC-hs (although nothing a 622 ATM link can't handle).
+
+static class DummyDropTailClass:public TclClass {
+public:
+   DummyDropTailClass():TclClass("Queue/DummyDropTail") {
+   } TclObject *create(int, const char *const *) {
+      return (new DummyDropTail);
+   }
+}
+
+class_dummy_drop_tail;
+
+void DummyDropTail::enque(Packet * p)
+{
+   if (summarystats) {
+      Queue::updateStats(qib_ ? q_->byteLength() : q_->length());
+   }
+   q_->enque(p);
+}
diff -urN ns-2.30-orig/umts/dummy_drop_tail.h ns-2.30-eu112/umts/dummy_drop_tail.h
--- ns-2.30-orig/umts/dummy_drop_tail.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/dummy_drop_tail.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: dummy_drop_tail.h,v 1.2 2004/01/20 13:29:24 simon Exp $
+ */
+
+#ifndef ns_dummy_drop_tail_h
+#define ns_dummy_drop_tail_h
+
+#include "drop-tail.h"
+
+/*
+ * A bounded, drop-tail queue
+ */
+class DummyDropTail:public DropTail {
+public:
+   void        enque(Packet * p);
+};
+
+#endif
diff -urN ns-2.30-orig/umts/error_model.cc ns-2.30-eu112/umts/error_model.cc
--- ns-2.30-orig/umts/error_model.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/error_model.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: error_model.cc,v 1.5 2004/01/29 11:08:30 wtdavid Exp $
+ */
+
+#include "error_model.h"
+
+UmtsErrorModel::UmtsErrorModel(double tti)
+{
+   tti_ = tti;
+   init_ = 0;
+   nrec_ = 0;
+}
+
+void UmtsErrorModel::attachTraceFile(char *filename)
+{
+   line       *t;
+   FILE       *fp;              // filepointer
+   char temp_line[LINE_LENGTH + 1]; // Last char for ending 0
+
+   if ((fp = fopen(filename, "r")) == NULL) {
+      printf("can't open file %s\n", filename);
+      exit(1);
+   }
+   // count number of lines
+   while (fgets(temp_line, LINE_LENGTH - 1, fp)) {
+      if (*temp_line != '%') {
+         nrec_++;
+      }
+   }
+   rewind(fp);
+
+   trace_ = new struct line[nrec_];
+
+   t = trace_;
+   for (int i = 0; i < nrec_; i++) {
+      fgets(temp_line, LINE_LENGTH - 1, fp);
+      int res =
+            sscanf(temp_line, "%f %f %f %d", &(t->rx1), &(t->rx2), &(t->rx3),
+                   &(t->cqi));
+      if (res == 4) {
+         // only increase the counter when the complete line has been correctly
+         // read. In other cases (i.e. (hopefully) comments) skip this line.
+         t++;
+      } else if (res == EOF) {
+         break;
+      }
+   }
+
+   fclose(fp);
+   init_ = 1;
+}
+
+line       *UmtsErrorModel::getElementAt(double time)
+{
+   if (init_ == 1) {
+      int rec = (int) (time / tti_);
+
+      if (rec >= nrec_) {
+         // After the end of the tracefile
+         printf("CQI + received powers tracefile is not large enough.\n");
+         exit(1);
+      }
+      return &(trace_[rec]);
+   } else {
+      return NULL;
+   }
+}
diff -urN ns-2.30-orig/umts/error_model.h ns-2.30-eu112/umts/error_model.h
--- ns-2.30-orig/umts/error_model.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/error_model.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: error_model.h,v 1.4 2004/01/29 11:08:30 wtdavid Exp $
+ */
+
+
+#ifndef ns_error_model_h
+#define ns_error_model_h
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LINE_LENGTH 140
+
+struct line {
+   float       rx1;
+   float       rx2;
+   float       rx3;
+   int         cqi;
+};
+
+class UmtsErrorModel {
+public:
+   UmtsErrorModel(double tti);
+   void        attachTraceFile(char *filename);
+   line       *getElementAt(double time);
+private:
+   struct line *trace_;
+   int         init_;
+   float       tti_;
+   int         nrec_;
+};
+
+
+#endif
diff -urN ns-2.30-orig/umts/hsdpalink.cc ns-2.30-eu112/umts/hsdpalink.cc
--- ns-2.30-orig/umts/hsdpalink.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/hsdpalink.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,1296 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: hsdpalink.cc,v 1.2 2005/09/22 13:05:12 neill Exp $
+ */
+
+#include "hsdpalink.h"
+#include "random.h"
+#include "am-hs.h"
+#include "cqi.h"
+#include "error_model.h"
+#include "math.h"
+#include <assert.h>
+#include <cassert>
+#include <stdlib.h>
+
+// These variables are used as 'super-globals', in this way the AM-HS object
+// and the MAC-hs object at the BS can be reached.
+
+extern RLC_HS *rlc_address;      // defined in am-hs.cc
+HsdpaMac   *mac_address;        // points to the object in the BS
+
+/*
+ * HsdpaMac
+ */
+
+int hdr_mac_hs::offset_;
+
+static class MAC_HSHeaderClass:public PacketHeaderClass {
+
+public:
+   MAC_HSHeaderClass():PacketHeaderClass("PacketHeader/MAC_HS",
+                                         sizeof(hdr_mac_hs)) {
+
+      bind_offset(&hdr_mac_hs::offset_);
+
+   }
+} class_machhshdr;
+
+
+
+
+static class HsdpaMacClass:public TclClass {
+public:
+   HsdpaMacClass():TclClass("Mac/Hsdpa") {
+   } TclObject *create(int, const char *const *) {
+      return (new HsdpaMac);
+   }
+}
+
+hsdpa_class_mac;
+
+HsdpaMac::HsdpaMac():VirtualUmtsMac(), current_proc_num_(0), frame_timer_((VirtualUmtsMac *) this,
+                                                     MACHS_TIMER_FRAME),
+cred_alloc_timer_((VirtualUmtsMac *) this, MACHS_TIMER_CREDALLOC),
+scheduler_timer_((VirtualUmtsMac *) this, MACHS_TIMER_SCHEDULE)
+{
+
+   // We set this global variable so that AM-HS can read this value and use the
+   // pointer to this object. Because multiple Mac-HS-es are instantiated,
+   // because we want the AM-HS to have the address of the Mac-HS located in the
+   // RLC, and because the Mac-HS located in the RLC is instantiated the first,
+   // we set this mac_address only when it isn't set already.
+   if (mac_address == 0) {
+      mac_address = this;
+   }
+
+   bind_time("TTI_", &TTI_);
+   bind("credit_allocation_interval_", &creditAllocationInterval_);
+   bind_time("flow_control_rtt_", &flow_control_rtt_);
+   bind_time("ack_process_delay_", &ack_process_delay_);
+   bind_time("stall_timer_delay_", &stall_timer_delay_);
+   bind("flow_max_", &flow_max_);
+   bind("priority_max_", &priority_max_);
+   bind("scheduler_type_", &scheduler_type_);
+   bind("max_mac_hs_buffer_level_", &max_mac_hs_buffer_level_);
+   bind("mac_hs_headersize_", &mac_hs_headersize_);
+   bind("flow_control_mode_", &flow_control_mode_);
+   bind("nr_harq_rtx_", &nr_harq_rtx_);
+   bind("nr_harq_processes_", &nr_harq_processes_);
+   bind("reord_buf_size_", &reord_buf_size_);
+   bind("alpha_", &alpha_);
+  
+   // credit_allocation_interval_ is specified in numbers of TTIs, for our
+   // timer, we need it in seconds.
+   creditAllocationTimeoutInterval_ = TTI_ * creditAllocationInterval_;
+
+   // init harq process_
+   for (int i = 0; i < nr_harq_processes_; i++) {
+      harq_process *temp_hp = new harq_process(this);
+
+      temp_hp->isFree_ = true;
+      process_.push_back(temp_hp);
+   }
+
+
+   // init filtered/relative power and cqi values (for fair scheduling)
+   // set to -999.0 so that we can determine the first setting of p_filtered
+   // and the variance
+   for (int i = 0; i < flow_max_; i++) {
+     p_filtered_.push_back(-999.0);
+     var_filtered_.push_back(-999.0);
+   }
+
+   
+   // init q_
+   for (int i = 0; i < priority_max_ * flow_max_; i++) {
+      umtsQueue  *temp_hq = new umtsQueue;
+
+      temp_hq->tx_seq_nr_ = 0;
+      q_.push_back(temp_hq);
+   }
+
+   rcwWindow_Size_ = reord_buf_size_ / 2;
+
+   // init reord_
+   for (int i = 0; i < priority_max_; i++) {
+      reord_mac_hs *temp_mh = new reord_mac_hs(this);
+
+      temp_mh->next_expected_TSN_ = 0;
+      temp_mh->T1_TSN_ = -1;
+      temp_mh->rcvWindow_UpperEdge_ = -1; // reord_buf_size_ - 1;
+      // TODO: This upperEdge value is not according to the standard, but this works.
+      // a better solution would be to rewrite some of the reordering code to store
+      // wrapped ( modulo reord_buf_size_ ) TSNs to access the reordering buffer.
+      for (int j = 0; j < reord_buf_size_; j++) {
+         vector < Packet * >*temp_pv = new vector < Packet * >;
+
+         temp_mh->reord_buffer_.push_back(temp_pv);
+      }
+      reord_.push_back(temp_mh);
+   }
+
+   // init credits_allocated_
+   for (int i = 0; i < priority_max_ * flow_max_; i++) {
+      credits_allocated_.push_back(0);
+   }
+
+   // init new_rlc_credits_
+   for (int i = 0; i < priority_max_ * flow_max_; i++) {
+      new_rlc_credits_.push_back(0);
+   }
+
+
+   for (int i = 0; i < flow_max_; i++) {
+      errorModel_.push_back( new UmtsErrorModel(TTI_) );
+      activated_.push_back(false);
+   }
+
+
+}
+
+int HsdpaMac::command(int argc, const char *const *argv)
+{
+   if (argc == 2) {
+      Tcl & tcl = Tcl::instance();
+      if (strcmp(argv[1], "set_access_delay") == 0) {
+         // do nothing
+         return TCL_OK;
+      } else if (strcmp(argv[1], "TTI") == 0) {
+         tcl.resultf("%f", TTI_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "BW") == 0) {
+         tcl.resultf("%f", bandwidth_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "start_TTI") == 0) {
+         // Start both the Frame Timer (which is resonsible for sending packets
+         // to the physical layer every TTI) and the Scheduler Timer (which is
+         // responsible for the scheduling every TTI). The scheduling will
+         // always happen just before the sending.
+         frame_timer_.sched(TTI_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "start_sched") == 0) {
+         scheduler_timer_.sched(TTI_ - 0.0002);
+         return TCL_OK;
+      }
+   } else if (argc == 3) {
+      if (strcmp(argv[1], "SA") == 0) {
+         index_ = atoi(argv[2]);
+         // index_ is defined in mac.h and is the MAC address.
+
+         return TCL_OK;
+      } else if (strcmp(argv[1], "loadSnrBlerMatrix") == 0) {
+         // Loads the SNR-BLER-Matix
+         char       *filename = new char[strlen(argv[2]) + 1];
+
+         strcpy(filename, argv[2]);
+         loadSnrBlerMatrix(filename);
+         return TCL_OK;
+      }
+   } else if (argc == 4) {
+      if (strcmp(argv[1], "setErrorTrace") == 0) {
+         // Loads the error trace for a certain user
+         int flowID = atoi(argv[2]);
+         char       *filename = new char[strlen(argv[3]) + 1];
+
+         strcpy(filename, argv[3]);
+         errorModel_.at(flowID)->attachTraceFile(filename);
+         activated_.at(flowID) = true;
+         return TCL_OK;
+      }
+   }
+   return Mac::command(argc, argv);
+}
+
+
+/////////////////////////////////////////////////////
+//                                                 //
+//  Timer - Timeout actions                        //
+//                                                 //
+/////////////////////////////////////////////////////
+
+void HsdpaMac::timeout(int tno)
+{
+
+   assert(current_proc_num_ >= 0 && current_proc_num_ < nr_harq_processes_);
+
+   switch (tno) {
+     case MACHS_TIMER_FRAME:
+        // Send scheduled MAC-hs PDU to downtarget_ (Physical layer object)
+
+        //1. send pdu to downtarget
+        //2. update next_proc_num
+        //3. reschedule a new TTI timer event
+        
+        if (!(process_.at(current_proc_num_)->isFree_)) {
+           Packet     *temp_p =
+                 (process_.at(current_proc_num_)->proc_pdu_)->copy();
+
+           // Mark MAC-hs PDU according to HARQ transmission number 
+           hdr_cmn   *ch;
+           ch = HDR_CMN(temp_p);
+           if ( process_.at(current_proc_num_)->tx_number_ == 1) {
+             ch->ptype() = PT_AMDA_H1;
+           } else if (process_.at(current_proc_num_)->tx_number_ == 2) {
+             ch->ptype() = PT_AMDA_H2;
+           } else if (process_.at(current_proc_num_)->tx_number_ == 3) {
+             ch->ptype() = PT_AMDA_H3;
+           }
+           //assert(hdr_cmn::access(temp_p)->direction() == hdr_cmn::DOWN);
+
+           hdr_cmn::access(temp_p)->direction() = hdr_cmn::DOWN;
+           downtarget_->recv(temp_p);
+        }
+        current_proc_num_ = (current_proc_num_ + 1) % nr_harq_processes_;
+        frame_timer_.resched(TTI_);
+        break;
+     case MACHS_TIMER_CREDALLOC:
+        // Perform Credit Allocation to RLC
+
+
+	//umhs_address->credit_update(new_rlc_credits_);
+        rlc_address->credit_update(new_rlc_credits_);
+
+        break;
+     case MACHS_TIMER_SCHEDULE:
+        // Schedule PDUs in priority buffers
+        HS_schedule();
+        // Schedule a new PDU schedule for every TTI
+        scheduler_timer_.resched(TTI_);
+        break;
+     case MACHS_TIMER_REORDER_STALL:
+        // Reordering Queue Stall Timer
+        for (unsigned int i = 0; i < reord_.size(); i++) {
+           if (Scheduler::instance().clock() >=
+               reord_.at(i)->stall_timer_.timeOfExpiry()
+               &&
+               ((reord_.at(i)->stall_timer_.status() ==
+                 reord_.at(i)->stall_timer_.TIMER_HANDLING)
+                || (reord_.at(i)->stall_timer_.status() == TIMER_PENDING))) {
+              t1_expire(i);
+           }
+        }
+
+        break;
+     case MACHS_TIMER_PROCESS_CLEAR:
+        for (unsigned int i = 0; i < process_.size(); i++) {
+
+           if (Scheduler::instance().clock()
+               >= process_.at(i)->clear_process_timer.timeOfExpiry()
+               &&
+               ((process_.at(i)->clear_process_timer.status() ==
+                 process_.at(i)->clear_process_timer.TIMER_HANDLING)
+                || (process_.at(i)->clear_process_timer.status() ==
+                    TIMER_PENDING))
+                 ) {
+
+              // Mark process as free
+              process_.at(i)->isFree_ = true;
+              Packet::free(process_.at(i)->proc_pdu_);
+              process_.at(i)->proc_pdu_ = NULL;
+           }
+        }
+
+        break;
+     default:
+        break;
+
+   }
+}
+
+void HsdpaMac::recv(Packet * p, Handler * h)
+{
+   struct hdr_cmn *hdr = HDR_CMN(p);
+
+   switch (hdr->direction()) {
+     case hdr_cmn::DOWN:
+        sendDown(p);
+        return;
+     case hdr_cmn::UP:
+        sendUp(p);
+        break;
+     default:
+        sendUp(p);
+   }
+}
+
+/////////////////////////////////////////////////////
+//                                                 //
+//  SendUp - UE ACK/NACK and Reordering            //
+//                                                 //
+//  -- process packets coming from phy-layer       //
+/////////////////////////////////////////////////////
+
+void HsdpaMac::t1_expire(int priority_id)
+{
+   int tsn;
+
+   for (tsn = reord_.at(priority_id)->next_expected_TSN_;
+        tsn <= reord_.at(priority_id)->T1_TSN_ - 1; tsn++) {
+      if (reord_.at(priority_id)->reord_buffer_.at(tsn % reord_buf_size_)->
+          size() != 0) {
+         ro_passUp(priority_id, tsn);
+      }
+   }
+
+   tsn = reord_.at(priority_id)->T1_TSN_;
+   while (reord_.at(priority_id)->reord_buffer_.at(tsn % reord_buf_size_)->
+          size() != 0) {
+      ro_passUp(priority_id, tsn);
+      tsn++;
+   }
+
+   reord_.at(priority_id)->next_expected_TSN_ = tsn;
+
+   t1_stop(priority_id);
+}
+
+void HsdpaMac::t1_stop(int priority_id)
+{
+   int tsn = reord_.at(priority_id)->rcvWindow_UpperEdge_;
+
+   while (ro_isInsideWindow(priority_id, tsn)) {
+      if (reord_.at(priority_id)->reord_buffer_.at(tsn % reord_buf_size_)->
+          size() != 0) {
+         t1_schedule(priority_id, tsn);
+         break;
+      }
+      if (tsn > 0) {            // prevent negative TSNs
+         tsn--;
+      } else {
+         break;
+      }
+   }
+}
+
+void HsdpaMac::t1_cancel(int priority_id)
+{
+   reord_.at(priority_id)->stall_timer_.cancel();
+   t1_stop(priority_id);
+}
+
+void HsdpaMac::t1_schedule(int priority_id, int tsn)
+{
+   if (reord_.at(priority_id)->stall_timer_.status() != TIMER_PENDING) {
+      reord_.at(priority_id)->T1_TSN_ = tsn;
+      reord_.at(priority_id)->stall_timer_.resched(stall_timer_delay_);
+   }
+}
+
+
+
+void HsdpaMac::sendUp(Packet * p)
+{
+   // UE MAC-hs Functionality
+
+   // Reordering: Implemented from method defined in 3GPP TS25.321 v6.0.0
+   //             Section 11.6.2.3, in v5.6.0 this method contains bugs
+
+
+   hdr_mac_hs *hsh = hdr_mac_hs::access(p);
+   hdr_cmn    *ch = hdr_cmn::access(p);
+   int priority_id = hsh->priority_id();
+   int tsn = hsh->ts_num();
+   int harq_process_id = hsh->proc_num();
+   harq_process *process = mac_address->getHARQProcess(harq_process_id);
+   hdr_mac    *mh = HDR_MAC(p);
+
+
+   if ((this->hdr_dst((char *) mh)) != index_) {
+      // Free packet when it is not for us.
+      Packet::free(p);
+      return;
+   }
+
+   if (ch->error() == 0) {
+
+
+      // Check if stall timer is required and none exists
+      if (tsn > reord_.at(priority_id)->next_expected_TSN_) {
+         t1_schedule(priority_id, tsn);
+      }
+
+      if (ro_isInsideWindow(priority_id, tsn)) {
+
+         // Place MAC-hs PDU in reorder buffer if not less than next expected TSN
+         if (tsn >= reord_.at(priority_id)->next_expected_TSN_) {
+            ro_placeInBuffer(priority_id, tsn, process);
+         }
+
+      } else {
+
+         // If TSN is located outside of receiver window
+         ro_placeInBuffer(priority_id, tsn, process);
+
+         //this is the only time the UpperEdge_ is updated
+         reord_.at(priority_id)->rcvWindow_UpperEdge_ = tsn;
+
+         int upperEdge = reord_.at(priority_id)->rcvWindow_UpperEdge_;
+
+
+	 // Define the upper and lower limits of the space outside the Reordering window
+	 int lower_index = max(0, (upperEdge - reord_buf_size_ + 1));
+	 int upper_index = max(0, (upperEdge - rcwWindow_Size_));
+
+          // Pass any PDUs in this space up to be disassembled
+         for (int i = lower_index; i< upper_index; i++) {
+            if (reord_.at(priority_id)->reord_buffer_.at(i % reord_buf_size_)->
+                size() != 0) {
+               ro_passUp(priority_id, tsn);
+            }
+         }
+
+	 // If next_expected_TSN is outside the Reordering window, set it to be equal to TSN of last in window
+	 if (reord_.at(priority_id)->next_expected_TSN_ <= (upperEdge - rcwWindow_Size_)) {
+	   
+	   reord_.at(priority_id)->next_expected_TSN_ =
+	     upperEdge + 1 - rcwWindow_Size_;
+	   
+	   int sn = reord_.at(priority_id)->next_expected_TSN_;
+    	   
+	   // Pass up all consecutive waiting PDUs in the Reordering window after update of next_expected_TSN 
+	   while (reord_.at(priority_id)->reord_buffer_.at(sn % reord_buf_size_)->
+		  size() != 0) {
+	     ro_passUp(priority_id, sn);
+	     sn++;
+	   }
+	   
+	   // Update next expected TSN to the first not received PDU
+	   reord_.at(priority_id)->next_expected_TSN_ = sn;
+	 }
+         
+      }
+         
+      //Clear HARQ process
+      if (process->clear_process_timer.status() != TIMER_PENDING) {
+         process->clear_process_timer.sched(ack_process_delay_);
+      }
+
+   } else {
+      // The PDU was not received properly
+      // Is this the last possible transmission of this PDU?
+      if (process->tx_number_ == nr_harq_rtx_) {
+         ro_stopTransmission(process);
+
+      } else {
+	// Is the TSN of the PDU outside the reordering window?
+	// If it is, we dont want to retransmit it, so clear the associated process 
+	if (tsn <= (reord_.at(priority_id)->rcvWindow_UpperEdge_ - rcwWindow_Size_)){
+	  
+	  // This is done here for the transmitter operation. The transmitter
+	  // should not retransmit packets that are outside the window. It
+	  // would be nicer when this part was implemented at the transmitter,
+	  // but it's much easier to implement it here.
+	  ro_stopTransmission(process);
+	  
+         } else {
+            // Increment number of transmissions for this HARQ process
+            process->tx_number_++;
+         }
+      }
+   }                            // End of non-acked PDU conditional check
+
+   Packet::free(p);             // delete the mac-hs pdu after processing.
+}
+
+bool HsdpaMac::ro_isInsideWindow(int priority_id, int tsn)
+{
+   bool inwin = (tsn <= reord_.at(priority_id)->rcvWindow_UpperEdge_);
+   inwin = inwin && (tsn > (reord_.at(priority_id)->rcvWindow_UpperEdge_
+                              - rcwWindow_Size_));
+   return inwin;
+}
+
+void HsdpaMac::ro_placeInBuffer(int priority_id, int tsn,
+                                harq_process * process)
+{
+   // Place each individual Mac-d PDU in the reordering. We can't place whole
+   // Mac-hs PDUs in this buffer, because these Mac-hs PDUs are re-used.
+   if (reord_.at(priority_id)->reord_buffer_.at(tsn % reord_buf_size_)->size() != 0){
+	   printf("ro_placeInBuffer: OVERWRITING\n");
+   }
+   reord_.at(priority_id)->reord_buffer_.at(tsn % reord_buf_size_)->clear();
+   for (unsigned int i = 0; i < process->pdu_vector_.size(); i++) {
+      reord_.at(priority_id)->reord_buffer_.at(tsn %
+                                               reord_buf_size_)->
+            push_back(process->pdu_vector_.at(i));
+   }
+   if (tsn == reord_.at(priority_id)->next_expected_TSN_) {
+     // Disassemble all consecutive received PDUs
+     int sn = reord_.at(priority_id)->next_expected_TSN_;
+     
+     while (reord_.at(priority_id)->reord_buffer_.at(sn % reord_buf_size_)->
+	    size() != 0) {
+       ro_passUp(priority_id, sn);
+       sn++;
+     }
+     
+     // Update next expected TSN to the first not received PDU
+     reord_.at(priority_id)->next_expected_TSN_ = sn;
+   }
+   
+}
+
+void HsdpaMac::ro_passUp(int priority_id, int tsn)
+{
+   // Dissamble PDU
+   hspdu_disassemble(reord_.at(priority_id)->reord_buffer_.
+                     at(tsn % reord_buf_size_));
+   //Remove pduvector from reordering vector
+   reord_.at(priority_id)->reord_buffer_.at(tsn % reord_buf_size_)->clear();
+   if (tsn == reord_.at(priority_id)->T1_TSN_) {
+      t1_cancel(priority_id);
+   }
+}
+
+void HsdpaMac::ro_stopTransmission(harq_process * process)
+{
+   // Clear HARQ process as it is outside the receiver window
+   if (process->clear_process_timer.status() != TIMER_PENDING) {
+      process->clear_process_timer.sched(ack_process_delay_);
+   }
+   //unpack the mac-hs pdu and free all the included mac-d pdus
+   for (unsigned int i = 0; i < process->pdu_vector_.size(); i++) {
+      Packet::free(process->pdu_vector_.at(i));
+   }
+}
+
+// This method returns a pointer to the actual harq_process. This method is
+// called by the MAC-hs in the UEs to get the processes that reside in the
+// MAC-hs in the BS.
+
+harq_process *HsdpaMac::getHARQProcess(int process)
+{
+   return process_.at(process);
+}
+
+/////////////////////////////////////////////////////
+//                                                 //
+//  MAC-hs PDU Disassemble                         //
+//                                                 //
+/////////////////////////////////////////////////////
+
+void HsdpaMac::hspdu_disassemble(vector < Packet * >*pdu_vect)
+{
+
+   // Send the individual PDUs up to the AM RLC in the UE
+   for (unsigned int i = 0; i < pdu_vect->size(); i++) {
+
+      // Because these small MAC-d PDU are transported inside a MAC-hs PDU the
+      // new direction hasn't been set yet.
+      (hdr_cmn::access(pdu_vect->at(i)))->direction() = hdr_cmn::UP;
+      uptarget_->recv(pdu_vect->at(i));
+   }
+}
+
+
+
+/////////////////////////////////////////////////////
+//                                                 //
+//  SendDown - Packet Enquing at MAC-hs            //
+//                                                 //
+/////////////////////////////////////////////////////
+
+void HsdpaMac::sendDown(Packet * p)
+{
+
+   // Enque PDUs from RLC in their appropriate buffer
+
+   hdr_ip     *piph = hdr_ip::access(p);
+   int flow_ = piph->flowid();
+   int priority_ = piph->prio();
+
+
+   // Check if the appropriate is full (over buffer MAX level
+   // Drop packet if TRUE
+   // Else, enque in the buffer:
+
+   // Nail wants to keep this here for posterity:
+   //      int index = ((flow_max_ * priority_)- (flow_max_ - flow_) - 1);
+   // index is determined by having flow_max_ flows for each priority
+   int index = priority_ * flow_max_ + flow_;
+
+   credits_allocated_.at(index)--;
+
+   if ((q_.at(index)->length()) >= max_mac_hs_buffer_level_) {
+      // This shouldn't happen. When this does happen it probably indicated an
+      // error in the credit allocation algorithm.
+      drop(p);
+   } else {
+      assert(hdr_cmn::access(p)->direction() == hdr_cmn::DOWN);
+      q_.at(index)->enque(p);
+   }
+
+   //Note: Buffers indexed: f1p1,f2p1,f3p1,f1p2,f2p2,f3p2,f1p3...
+
+}
+
+
+/////////////////////////////////////////////////////
+//                                                 //
+//  Credit Allocation                              //
+//                                                 //
+/////////////////////////////////////////////////////
+
+void HsdpaMac::cred_alloc(vector < int >*pdu_pend_)
+{
+   // Determine which Node B Flow Control is to be used
+   // 1: per flow (default) 2: per node
+
+
+   if (flow_control_mode_ == 1) {
+
+      //1. determine credits pending from credit allocation vector
+      //   (use Interval and flow control RTT values)
+      //2. determine current buffersizes at MAC-hs
+      //3. new credit allocation is minimum of pdu_pend_ and
+      //   (Max buffer level - buffersize - credits pending)
+      //4. update credits alocated vector
+      //5. schedule update of credit allocation in AM RLC (delayed by Iub Delay)
+
+
+
+      for (int index = 0; index < (flow_max_ * priority_max_); index++) {
+
+
+
+         new_rlc_credits_.at(index) =
+               min(pdu_pend_->at(index),
+                   (max_mac_hs_buffer_level_ - q_.at(index)->length() -
+                    credits_allocated_.at(index)));
+         credits_allocated_.at(index) += new_rlc_credits_.at(index);
+
+
+      }
+
+      // Schedule credit_update in RLC, with Iub delay
+      cred_alloc_timer_.sched(flow_control_rtt_ / 2);
+
+   } else if (flow_control_mode_ == 2) {
+
+      // CQI averaged over window, for each buffer
+      // averaging window size set
+      //
+
+   } else {
+      //Error message here as no correct flow control mode has been set
+   }
+}
+
+// Used to deallocate credits whenever the RLC Window blocks packets from
+// // being sent to the Node B. Called from AM-HS::Credit_Update.
+void HsdpaMac::remove_credit_allocation(int q_index)
+{
+  if (credits_allocated_.at(q_index) > 0) {
+     credits_allocated_.at(q_index) = credits_allocated_.at(q_index) - 1;
+  }
+}
+
+
+/////////////////////////////////////////////////////
+//                                                 //
+//  Scheduling                                     //
+//                                                 //
+/////////////////////////////////////////////////////
+
+int HsdpaMac::ScheduleRoundRobin()
+{
+  int index = -1;              // Queue-id, flow-priority combination
+  int flowID;
+  int max_num_pdus = 0;
+  int pdu_size = 0;
+
+   // Round Robin Scheduling
+   //set index to equal the buffer index with the longest waiting head packet
+   double min_arrival_time = Scheduler::instance().clock();
+
+   for (int j = 0; j < flow_max_ * priority_max_; j++) {
+      flowID = j % flow_max_; // this should be correct ;-)
+
+
+      if (q_.at(j)->lastServedTime_ < min_arrival_time
+         && q_.at(j)->length() > 0) {
+
+         // CHECK: this should normally be 40 (set in ns-default)
+         pdu_size = q_.at(j)->getPacketSize();
+        
+
+         // only schedule for queues that have a high enough CQI to actually send packets
+         max_num_pdus = calc_num_pdus(flowID, pdu_size);
+
+
+         if ( max_num_pdus > 0 ) {
+            min_arrival_time = q_.at(j)->lastServedTime_;
+            index = j;
+         }
+      }
+   }
+   // If all queues are empty, index will stay -1 and the rest of the
+   // method will be skipped.
+
+   return index;
+
+}
+
+int HsdpaMac::ScheduleCoverI()
+{
+   // C/I Scheduling
+   int index = -1;
+   int max_num_pdus = 0;
+   int pdu_size = 0;
+
+   static vector < int > temp_cqi_vector_;
+   static vector < int > temp_fid_vector_;
+
+   temp_fid_vector_.clear();
+   temp_cqi_vector_.clear();
+
+   // Check for activated flows
+
+   for (int i = 0; i < flow_max_; i++) {
+
+      if (activated_.at(i) == TRUE) {
+
+         // get CQI for this flow
+         line       *tempLine = getLine(i);
+
+         // insert CQI into a temp vector of CQI values per flow (0 value means inactive)
+         temp_cqi_vector_.push_back(tempLine->cqi);
+         temp_fid_vector_.push_back(i);
+      }
+   }
+
+
+
+   // We now have 2 vectors (of the same size) with all the cqi and fids
+
+   // Straight Insertion sorting of vectors
+
+   int temp_cqi_val, temp_fid_val;
+
+   for (unsigned int i = 1; i < temp_cqi_vector_.size(); i++) {
+
+      temp_cqi_val = temp_cqi_vector_.at(i);
+      temp_fid_val = temp_fid_vector_.at(i);
+
+      int j = i - 1;
+
+      while (j >= 0 && temp_cqi_vector_.at(j) < temp_cqi_val) {
+         temp_cqi_vector_.at(j + 1) = temp_cqi_vector_.at(j);
+         temp_fid_vector_.at(j + 1) = temp_fid_vector_.at(j);
+         j--;
+      }
+
+      temp_cqi_vector_.at(j + 1) = temp_cqi_val;
+      temp_fid_vector_.at(j + 1) = temp_fid_val;
+   }
+
+
+   // Loop through the priorities of each flow, in order
+
+   for (unsigned int i = 0; i < temp_fid_vector_.size(); i++) {
+
+      
+
+      for (int j = 0; j < priority_max_; j++) {
+        
+        pdu_size = q_.at((j* flow_max_)+ temp_fid_vector_.at(i))->getPacketSize();
+        max_num_pdus = calc_num_pdus(temp_fid_vector_.at(i), pdu_size);
+        
+         // Set index to the first priority/flow that has packets waiting
+         if ( (q_.at((j * flow_max_) + temp_fid_vector_.at(i))->length() >
+            0) && (max_num_pdus > 0) ) {
+            index = ((j * flow_max_) + temp_fid_vector_.at(i));
+         }
+         // Break out of priority loop if index has been set
+         if (index >= 0) {
+            break;
+         }
+
+      }
+      // Break out of flow loop if index has been set
+      if (index >= 0) {
+         break;
+      }
+   }
+
+   return index;
+}
+
+int HsdpaMac::ScheduleFairChannel()
+{
+
+    int index = -1;
+    int max_num_pdus = 0;
+    int pdu_size = 0;
+    static vector < float > temp_power_vector_;
+    static vector < int > temp_fid_vector_;
+    static vector < float > temp_rel_power_vector_;
+
+    temp_power_vector_.clear();
+    temp_fid_vector_.clear();
+    temp_rel_power_vector_.clear();
+
+    // Check for activated flows
+    for (int i = 0; i < flow_max_; i++) {
+
+        if ( activated_.at(i) ) {
+
+            // get TTI input trace line for this flow
+            line *tempLine = getLine(i);
+
+            // insert first received power/flow id into temp vectors
+            temp_power_vector_.push_back(tempLine->rx1);
+            temp_fid_vector_.push_back(i);
+        }
+    }
+
+    int temp_fid_val;
+    float temp_pow_val;
+
+  // Calculate relative power for each active flow
+    for (unsigned int i = 0; i < temp_fid_vector_.size(); i++) {
+
+        //    temp_rel_power_vector_.push_back( temp_power_vector_.at(i) - p_filtered_.at(temp_fid_vector_.at(i)) );
+
+        if ( var_filtered_.at(i) > 0.0 ) {
+            float tmp;
+            tmp = temp_power_vector_.at(i) - p_filtered_.at(temp_fid_vector_.at(i) );
+            tmp = tmp / sqrt( var_filtered_.at( temp_fid_vector_.at(i) ) );
+            temp_rel_power_vector_.push_back( tmp );
+        } else {
+            temp_rel_power_vector_.push_back(0.0);
+        }
+    }
+
+
+
+
+    // Sort by Maximum relative CQI
+    for (unsigned int i = 1; i < temp_rel_power_vector_.size(); i++) {
+
+        temp_pow_val = temp_rel_power_vector_.at(i);
+        temp_fid_val = temp_fid_vector_.at(i);
+
+        int j = i - 1;
+
+        while (j >= 0 && temp_rel_power_vector_.at(j) < temp_pow_val) {
+            temp_rel_power_vector_.at(j + 1) = temp_rel_power_vector_.at(j);
+            temp_fid_vector_.at(j + 1) = temp_fid_vector_.at(j);
+            j--;
+        }
+        temp_rel_power_vector_.at(j + 1) = temp_pow_val;
+        temp_fid_vector_.at(j + 1) = temp_fid_val;
+    }
+
+
+
+    // Loop through the priorities of each flow, in order
+
+    for (unsigned int i = 0; i < temp_fid_vector_.size(); i++) {
+      
+
+      for (int j = 0; j < priority_max_; j++) {
+        
+        pdu_size = q_.at((j * flow_max_) + temp_fid_vector_.at(i))->getPacketSize();
+        max_num_pdus = calc_num_pdus(temp_fid_vector_.at(i), pdu_size);
+            // Set index to the first priority/flow that has packets waiting
+            if ( (q_.at((j * flow_max_) + temp_fid_vector_.at(i))->length() > 0) && (max_num_pdus > 0)) {
+                index = ((j * flow_max_) + temp_fid_vector_.at(i));
+            }
+            // Break out of priority loop if index has been set
+            if (index >= 0) {
+                break;
+            }
+
+        }
+        // Break out of flow loop if index has been set
+        if (index >= 0) {
+            break;
+        }
+    }
+
+    return index;
+
+}
+
+void HsdpaMac::HS_schedule()
+{
+
+   int index = -1;              // Queue-id, flow-priority combination
+   int flowID;
+   int max_num_pdus = 0;
+   int pdu_size = 0;
+
+   //Update p_filtered values for use in FCDS
+
+    for (int i = 0; i < flow_max_; i++) {
+
+        if (activated_.at(i) == TRUE) {
+
+            line       *tempLine = getLine(i);
+
+            if (p_filtered_.at(i) < -998.0) {
+
+                p_filtered_.at(i) = tempLine->rx1;
+                var_filtered_.at(i) = 0.0;
+            } else {
+                p_filtered_.at(i) = p_filtered_.at(i) * alpha_ +  (1 - alpha_) * tempLine->rx1;
+                var_filtered_.at(i) = var_filtered_.at(i) * alpha_ +
+                                        (1 - alpha_) *  pow( tempLine->rx1 - p_filtered_.at(i) ,2);
+            }
+
+        }
+
+    }
+
+   // If next process is free, schedule
+   if (process_.at(current_proc_num_)->isFree_) {
+      // Determine which scheduling algorithm is to be used
+      // 1: Round Robin 2: Maximum C/I 3: FCDS
+
+      if (scheduler_type_ == 1) {
+        index = ScheduleRoundRobin();
+      } else if (scheduler_type_ == 2) {
+        index = ScheduleCoverI();
+      } else if (scheduler_type_ == 3) {
+        index = ScheduleFairChannel();
+      } else {
+         //error: undefined scheduler
+      }
+
+
+      if (index >= 0) {
+        pdu_size = q_.at(index)->getPacketSize();
+      
+         // set flowID to the one we're going to use
+         flowID = index % flow_max_; // this should be correct ;-)
+
+         // Calculate the max number of MAC-d PDUs that will fit in a MAC-hs PDU
+         max_num_pdus = calc_num_pdus(flowID, pdu_size);
+
+
+         if (max_num_pdus > 0) {
+            //setup HARQ process for this user
+            setupHARQprocess(flowID);
+
+            // Generate MAC-hs PDU and assign to process struct
+            mac_hs_pdu_gen(index, max_num_pdus);
+            // Update TSN according to the size of reordering buffer (default size = 64)
+            q_.at(index)->tx_seq_nr_ = (q_.at(index)->tx_seq_nr_ + 1);
+         } else {
+         }
+      }
+   }
+
+}
+
+
+line  *HsdpaMac::getLine(int user_id){
+   line  *tempLine =
+         errorModel_.at(user_id)->getElementAt(Scheduler::instance().clock());
+
+   if (tempLine != NULL) {
+      // When the CQI value is out of range, we should set it to something that
+      // is in the range.
+      if (tempLine->cqi < 1) {
+         tempLine->cqi = 1;
+      }
+      if (tempLine->cqi > 30) {
+         tempLine->cqi = 30;
+      }
+   }
+   return tempLine;
+}
+
+
+/////////////////////////////////////////////////////
+//                                                 //
+// Calculate the maximum # of PDUs in MAC-hs PDU   //
+// Modifies global tb_size_                        //
+/////////////////////////////////////////////////////
+
+// pdu_size  relates to a MAC-d PDU size.
+int HsdpaMac::calc_num_pdus(int user_id, int pdu_size)
+{
+
+   // Read TBS from input trace file
+   // Calculate, using pdu_size, the # that will fit in TBS
+   // Use mac-hs header size (should be a default value)
+
+   int num_pdus = 0;
+
+   // if pdu_size is not usable, return 0
+   if (pdu_size <= 0) { return num_pdus; }
+
+   tb_size_ = 0; //global class variable
+
+   line  *tempLine = getLine(user_id);
+
+   if (tempLine != NULL) {
+      tb_size_ = cqiMapping[tempLine->cqi];
+   }
+
+   if (tb_size_ > mac_hs_headersize_) {
+      num_pdus = int ((tb_size_ - mac_hs_headersize_) / (pdu_size * 8));
+   }
+
+   return num_pdus;
+}
+
+
+/////////////////////////////////////////////////////
+//                                                 //
+// Setup HARQ process for this TTI
+//                                                 //
+/////////////////////////////////////////////////////
+
+void HsdpaMac::setupHARQprocess(int user_id)
+{
+
+   line  *tempLine = getLine(user_id); // read the input trace for clock.now
+
+
+   // Add first Rx power to process struct (from input trace file)
+   process_.at(current_proc_num_)->rx_powers_.clear();
+   process_.at(current_proc_num_)->rx_powers_.push_back(tempLine->rx1);
+   process_.at(current_proc_num_)->rx_powers_.push_back(tempLine->rx2);
+   process_.at(current_proc_num_)->rx_powers_.push_back(tempLine->rx3);
+
+   int temp_random = Random::integer(snrBlerMatrix_.size());
+
+   process_.at(current_proc_num_)->target_power =
+         snrBlerMatrix_.at(temp_random)->at(tempLine->cqi - 1);
+
+
+   // Add indication of 1st transmission to process struct
+   process_.at(current_proc_num_)->tx_number_ = 1;
+
+   // Add indication of process number to process struct
+   process_.at(current_proc_num_)->proc_number_ = current_proc_num_;
+
+   // Add indication of process status to process struct
+   process_.at(current_proc_num_)->isFree_ = false;
+
+}
+
+
+
+/////////////////////////////////////////////////////
+//                                                 //
+//  MAC-hs PDU Generation                          //
+//                                                 //
+/////////////////////////////////////////////////////
+
+
+void HsdpaMac::mac_hs_pdu_gen(int index, int max_pdus)
+{
+
+
+   // Create NS packet for MAC-hs PDU and store in process struct
+
+   Packet     *c = q_.at(index)->dequeCopy();
+
+   hdr_mac_hs *hsh;
+   hdr_cmn    *ch;
+   hdr_ip     *iph;
+   unsigned int deqLen = 0;
+
+   hsh = hdr_mac_hs::access(c);
+   ch = HDR_CMN(c);
+   iph = hdr_ip::access(c);
+
+   // Rename packet type for HARQ tracking
+   ch->ptype() = PT_AMDA_H1;
+
+   hsh->proc_num() = current_proc_num_;
+   hsh->priority_id() = iph->prio();
+   hsh->size_index_id() = pdu_size_;
+   hsh->num_pdus() = max_pdus;
+   hsh->ts_num() = q_.at(index)->tx_seq_nr_;
+
+   ch->size() = (int) floor(tb_size_ / 8.0);
+
+   process_.at(current_proc_num_)->proc_pdu_ = c;
+
+   process_.at(current_proc_num_)->pdu_vector_.clear();
+
+   deqLen = min(max_pdus, q_.at(index)->length());
+
+   // Deque buffer and form a vector of the pdu packets for a HARQ process
+   for (unsigned int i = 0; i < deqLen; i++) {
+      process_.at(current_proc_num_)->pdu_vector_.push_back(q_.at(index)->
+                                                            deque());
+   }
+}
+
+// This method will read a file that consists of a large number of values that
+// represent the minimum receive power for a successfull transmission. It
+// populates the snrBlerMatrix_ vector.
+
+void HsdpaMac::loadSnrBlerMatrix(char *filename)
+{
+
+   FILE       *fp;              // filepointer
+   char temp_line[LONG_LINE];
+   float temp_val[30];
+
+   if ((fp = fopen(filename, "r")) == NULL) {
+      fprintf(stderr, "can't open file %s\n", filename);
+      exit(1);
+   }
+
+   while (fgets(temp_line, LONG_LINE, fp)) {
+      // lines starting with % are comments and are ignored
+      if (*temp_line == '%') {
+         continue;
+      }
+      int res = sscanf(temp_line,
+                       "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
+                       &(temp_val[0]), &(temp_val[1]), &(temp_val[2]),
+                       &(temp_val[3]), &(temp_val[4]),
+                       &(temp_val[5]), &(temp_val[6]), &(temp_val[7]),
+                       &(temp_val[8]), &(temp_val[9]),
+                       &(temp_val[10]), &(temp_val[11]), &(temp_val[12]),
+                       &(temp_val[13]), &(temp_val[14]),
+                       &(temp_val[15]), &(temp_val[16]), &(temp_val[17]),
+                       &(temp_val[18]), &(temp_val[19]),
+                       &(temp_val[20]), &(temp_val[21]), &(temp_val[22]),
+                       &(temp_val[23]), &(temp_val[24]),
+                       &(temp_val[25]), &(temp_val[26]), &(temp_val[27]),
+                       &(temp_val[28]), &(temp_val[29])
+            );
+
+      if (res == 30) {
+         vector < double >*temp_vector = new vector < double >;
+
+         for (int i = 0; i < 30; i++) {
+            temp_vector->push_back(temp_val[i]);
+         }
+         snrBlerMatrix_.push_back(temp_vector);
+      } else {
+         // when not all 30 cqi values are read in correctly, stop the reading
+         // and processing of the file.
+         break;
+      }
+   }
+
+}
+
+
+static class HsdpaPhyClass:public TclClass {
+public:
+   HsdpaPhyClass():TclClass("Phy/Hsdpa") {
+   } TclObject *create(int, const char *const *) {
+      return (new HsdpaPhy);
+   }
+}
+
+class_HsdpaPhy;
+
+
+HsdpaPhy::HsdpaPhy():Phy()
+{
+}
+
+void HsdpaPhy::recv(Packet * p, Handler * h)
+{
+
+   struct hdr_cmn *hdr = HDR_CMN(p);
+
+   switch (hdr->direction()) {
+     case hdr_cmn::DOWN:
+        sendDown(p);
+        return;
+     case hdr_cmn::UP:
+        if (sendUp(p) == 0) {
+           Packet::free(p);
+           return;
+        } else {
+           uptarget_->recv(p, (Handler *) 0);
+        }
+        break;
+     default:
+        if (sendUp(p) == 0) {
+           Packet::free(p);
+           return;
+        } else {
+           uptarget_->recv(p, (Handler *) 0);
+        }
+   }
+}
+
+void HsdpaPhy::sendDown(Packet * p)
+{
+   hdr_cmn    *ch;
+
+   ch = hdr_cmn::access(p);
+
+   if (channel_ != NULL) {
+      channel_->recv(p, this);
+   } else {
+      Packet::free(p);
+   }
+}
+
+int HsdpaPhy::sendUp(Packet * p)
+{
+
+   hdr_mac_hs *hsh = hdr_mac_hs::access(p);
+   hdr_cmn    *ch = hdr_cmn::access(p);
+
+   int harq_process_id = hsh->proc_num();
+   harq_process *process = mac_address->getHARQProcess(harq_process_id);
+
+
+   if (process->rx_powers_[process->tx_number_ - 1] < process->target_power) {
+      ch->error() = 1;
+   } else {
+      ch->error() = 0;
+   }
+
+   return 1;
+}
+
+int HsdpaPhy::command(int argc, const char *const *argv)
+{
+   return Phy::command(argc, argv);
+}
+
+
diff -urN ns-2.30-orig/umts/hsdpalink.h ns-2.30-eu112/umts/hsdpalink.h
--- ns-2.30-orig/umts/hsdpalink.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/hsdpalink.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * Copyright (c) 2005 Twente Institute for Wireless and Mobile
+ *		Communications B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. or WMC may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: hsdpalink.h,v 1.3 2005/09/22 15:07:08 simon Exp $
+ */
+
+#ifndef ns_hsdpa_link_h
+#define ns_hsdpa_link_h
+
+#include "error_model.h"
+#include "phy.h"
+#include "virtual_umtsmac.h"
+#include <vector>
+#include "math.h"
+#include "umts-timers.h"
+#include "umts-queue.h"
+#include <stdio.h>
+
+
+#define LONG_LINE 500
+
+////////////////////////////HSDPA MAC//////////////////////////
+
+// Defines a new data structure for the MAC-hs PDU Header
+struct hdr_mac_hs {
+
+   int         proc_num_;       // Associated HARQ process number
+   int         priority_id_;    // Global Reordering Queue ID
+   int         ts_num_;         // Transmission Sequence Number (TSN)
+   int         size_index_id_;  // Size of the MAC-d PDUs
+   int         num_pdus_;       // Number of MAC-d PDUs (RLC PDUs)
+
+   static int  offset_;
+
+   inline int &offset() {
+      return offset_;
+   } static hdr_mac_hs *access(const Packet * p) {
+      return (hdr_mac_hs *) p->access(offset_);
+   }
+
+   int        &proc_num() {
+      return proc_num_;
+   }
+   int        &priority_id() {
+      return priority_id_;
+   }
+   int        &ts_num() {
+      return ts_num_;
+   }
+   int        &size_index_id() {
+      return size_index_id_;
+   }
+   int        &num_pdus() {
+      return num_pdus_;
+   }
+
+};
+
+
+class HsdpaMac;
+
+
+class harq_process {
+public:
+   harq_process(HsdpaMac * machs):clear_process_timer((VirtualUmtsMac *) machs,
+                                                      MACHS_TIMER_PROCESS_CLEAR)
+   {
+   } int       proc_number_;    // HARQ process number
+   int         tx_number_;      // Number of transmissions. From 1 to total number of retransmissions
+   vector<double> rx_powers_;   // Vector of received powers for all transmissions. Read in from external file.
+   double      target_power;    // The target power of the harq_process. When the received power is higher than this,
+
+   // the packet is received correctly.
+   bool        isFree_;         // Status of HARQ process. TRUE - Process is free, FALSE - Process is being used.
+
+   vector<Packet*> pdu_vector_;  // Vector of MAC-d PDUs which form the MAC-hs PDU ( RLC information retained)
+   Packet     *proc_pdu_;       // MAC-hs PDU, used for NS purposes.
+
+   HsdpaMacTimer clear_process_timer;  // Timer to simulate delay in processing ACK
+
+};
+
+// Defines a new data structure for the status of each reordering priority queue
+
+class reord_mac_hs {
+public:
+   reord_mac_hs(HsdpaMac * machs):stall_timer_((VirtualUmtsMac *) machs,
+                                               MACHS_TIMER_REORDER_STALL) {
+   } int       next_expected_TSN_;
+   int         T1_TSN_;
+   int         rcvWindow_UpperEdge_;
+
+   vector< vector<Packet*>* >  reord_buffer_;
+
+   HsdpaMacTimer stall_timer_;  // Timer used to help ensure reordering queue does not stall
+
+
+};
+
+class HsdpaMac:public VirtualUmtsMac {
+public:
+   HsdpaMac();
+   virtual void timeout(int tno);
+   void        sendUp(Packet * p);
+   void        sendDown(Packet * p);
+   void        cred_alloc(vector<int>* pdu_pend_);
+   void        recv(Packet * p, Handler * h);
+   void        remove_credit_allocation(int queue_index);
+
+   harq_process *getHARQProcess(int process);
+
+   //  hsdpaPhy getDowntarget();     // Returns the connected physical channel
+
+protected:
+   int         command(int argc, const char *const *argv);
+
+   int         current_proc_num_;   // Current HARQ stop-and-wait process
+   int         pdu_size_;       // MAC-d PDU size
+   int         tb_size_;        // Transport-block size in bits (dependent on CQI value)
+
+   // time between credit_allocs, is used to determine how large cred_pend_ should be
+   double      creditAllocationTimeoutInterval_;
+
+// variables initialised from TCL:
+   double      TTI_;
+   double      flow_control_rtt_;   // Round trip time of Flow Control (RTT of Iub + some
+   // CPU time)
+   double      ack_process_delay_;  // Delay of ACk being sent over control channel
+   double      stall_timer_delay_;  // Reordering Queue stall avoidance timer (see 3GPP
+   // TS25.321)
+   int         priority_max_;   // Maximum number of service priorities
+   int         flow_max_;       // Maximum number of flows
+   int         scheduler_type_; // 1. Round Robin 2. Maximum C/I
+   int         max_mac_hs_buffer_level_;
+   int         flow_control_mode_;  // 1. Per-flow 2. Per-node
+   int         nr_harq_rtx_;    // Max number of HARQ retransmissions
+   int         nr_harq_processes_;
+   int         reord_buf_size_; // Size in elements
+   int         mac_hs_headersize_;
+   int         creditAllocationInterval_; // The number of TTIs between a new
+                                          // credit allocation.
+   double       alpha_;                // Fair Channel Dependent Scheduling (FCDS) parameters
+
+// end variables from TCL
+
+    vector <harq_process*> process_;
+    vector <umtsQueue*>    q_;
+
+   int         rcwWindow_Size_;
+
+    vector <int> new_rlc_credits_;     // Credit allocation per queue
+    vector <int> credits_allocated_;   // Number of packets that are allocated,
+   // but not received yet
+
+    vector <reord_mac_hs*>  reord_; // Per priority queue
+
+    vector < vector<double>* >    snrBlerMatrix_;
+    vector <bool>  activated_;
+    vector <float> p_filtered_; // Filtered powers for FCDS
+    vector <float> var_filtered_; // variance for Filtered powers for FCDS
+
+    void        HS_schedule();
+    int         ScheduleRoundRobin();
+    int         ScheduleCoverI();
+    int         ScheduleFairChannel();
+
+    int         calc_num_pdus(int user_id, int pdu_size);
+    line        *getLine(int user_id);
+    void        setupHARQprocess(int user_id);
+    void        hspdu_disassemble(vector < Packet * >*pdu_vect);
+    void        mac_hs_pdu_gen(int buffer_index, int max_pdus);
+    void        loadSnrBlerMatrix(char *filename);
+
+    void        t1_expire(int priority_id);
+    void        t1_stop(int priority_id);
+    void        t1_cancel(int priority_id);
+    void        t1_schedule(int priority_id, int tsn);
+    bool        ro_isInsideWindow(int priority_id, int tsn);
+    void        ro_placeInBuffer(int priority_id, int tsn,
+                                    harq_process * process);
+    void        ro_passUp(int priority_id, int tsn);
+    void        ro_stopTransmission(harq_process * process);
+
+    HsdpaMacTimer frame_timer_;
+    HsdpaMacTimer cred_alloc_timer_;
+    HsdpaMacTimer scheduler_timer_;
+
+    vector <UmtsErrorModel*> errorModel_;
+
+};
+
+ ////////////////////////////PHY////////////////////////////
+
+class HsdpaPhy:public Phy {
+public:
+   HsdpaPhy();
+   void        recv(Packet * p, Handler * h);
+   void        sendDown(Packet * p);
+   int         sendUp(Packet * p);
+protected:
+   int         command(int argc, const char *const *argv);
+
+};
+
+#endif
diff -urN ns-2.30-orig/umts/networkInterface.cc ns-2.30-eu112/umts/networkInterface.cc
--- ns-2.30-orig/umts/networkInterface.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/networkInterface.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: networkInterface.cc,v 1.6 2004/01/21 08:40:08 wtdavid Exp $
+ */
+
+#include "networkInterface.h"
+
+static class UmtsNetworkInterfaceClass:public TclClass {
+public:
+   UmtsNetworkInterfaceClass():TclClass("UmtsNetworkInterface") {
+   } TclObject *create(int, const char *const *) {
+      return (new UmtsNetworkInterface);
+   }
+}
+
+class_Umtsnetworkinterface;
+
+
+int UmtsNetworkInterface::command(int argc, const char *const *argv)
+{
+   int returnvalue = NetworkInterface::command(argc, argv);
+
+   return returnvalue;
+}
+
+void UmtsNetworkInterface::recv(Packet * p, Handler * h)
+{
+   hdr_cmn    *ch = hdr_cmn::access(p);
+
+   ch->iface() = intf_label_;
+   send(p, h);
+}
+
+UmtsNetworkInterface::UmtsNetworkInterface():NetworkInterface()
+{
+}
diff -urN ns-2.30-orig/umts/networkInterface.h ns-2.30-eu112/umts/networkInterface.h
--- ns-2.30-orig/umts/networkInterface.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/networkInterface.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: networkInterface.h,v 1.4 2004/01/20 13:29:24 simon Exp $
+ */
+
+#ifndef ns_UmtsNetworkInterface_h
+#define ns_UmtsNetworkInterface_h
+
+#include "net-interface.h"
+#include "rlc.h"
+#include "um.h"
+
+class UmtsNetworkInterface:public NetworkInterface {
+public:
+   UmtsNetworkInterface();
+   int         command(int argc, const char *const *argv);
+   void        recv(Packet * p, Handler * h);
+};
+
+#endif
diff -urN ns-2.30-orig/umts/nif-classifier.cc ns-2.30-eu112/umts/nif-classifier.cc
--- ns-2.30-orig/umts/nif-classifier.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/nif-classifier.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: nif-classifier.cc,v 1.3 2004/01/20 13:29:24 simon Exp $
+ */
+
+#include "nif-classifier.h"
+
+static class NifClassifierClass:public TclClass {
+public:
+   NifClassifierClass():TclClass("Classifier/Nif") {
+   } TclObject *create(int, const char *const *) {
+      return (new NifClassifier());
+   }
+}
+
+class_nif_classifier;
+
+int NifClassifier::classify(Packet * p)
+{
+   hdr_cmn    *ch = hdr_cmn::access(p);
+
+   // Nif classifier returns the network interface of the packet.
+   return ch->iface();
+};
+
+int NifClassifier::command(int argc, const char *const *argv)
+{
+   return (Classifier::command(argc, argv));
+}
+
+NifClassifier::NifClassifier():Classifier()
+{
+}
diff -urN ns-2.30-orig/umts/nif-classifier.h ns-2.30-eu112/umts/nif-classifier.h
--- ns-2.30-orig/umts/nif-classifier.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/nif-classifier.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: nif-classifier.h,v 1.3 2004/01/20 13:29:24 simon Exp $
+ */
+
+#ifndef ns_classifier_nif_h
+#define ns_classifier_nif_h
+
+#include "packet.h"
+#include "ip.h"
+#include "classifier.h"
+
+class NifClassifier:public Classifier {
+public:
+   NifClassifier();
+   int         command(int argc, const char *const *argv);
+protected:
+   int         classify(Packet * p);
+};
+
+#endif
diff -urN ns-2.30-orig/umts/rlc.h ns-2.30-eu112/umts/rlc.h
--- ns-2.30-orig/umts/rlc.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/rlc.h	2006-10-07 22:58:42.000000000 +0307
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: rlc.h,v 1.1 2005/04/27 14:30:09 simon Exp $
+ */
+
+#ifndef ns_rlc_h
+#define ns_rlc_h
+
+#include "ll.h"
+#include "queue.h"
+#include "agent.h"
+#include "packet.h"
+#include "timer-handler.h"
+#include "umts-headers.h"
+#include <vector>
+
+class RLC: public LL {
+public:
+   RLC():LL() {
+   } virtual void timeout(int tno, int flowID = -1) = 0;
+   virtual void recv(Packet *, Handler *) = 0;
+};
+
+class RLC_HS: public RLC {
+public:
+   RLC_HS():RLC() {
+   } virtual void credit_update(vector < int >new_rlc_credits) = 0;
+};
+
+#endif
diff -urN ns-2.30-orig/umts/tcs.cc ns-2.30-eu112/umts/tcs.cc
--- ns-2.30-orig/umts/tcs.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/tcs.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: tcs.cc,v 1.1 2005/04/27 14:30:09 simon Exp $
+ */
+
+#include "packet.h"
+#include "tcs.h"
+#include "mac.h"
+#include <iostream>
+
+static class TCMClass:public TclClass {
+public:
+   TCMClass():TclClass("TrChMeasurer") {
+   } TclObject *create(int, const char *const *) {
+      return (new TCM);
+   }
+}
+
+class_tcm;
+
+static class CSClass:public TclClass {
+public:
+   CSClass():TclClass("ChannelSwitcher") {
+   } TclObject *create(int, const char *const *) {
+      return (new CS);
+   }
+}
+
+class_cs;
+
+
+void DownSwitch_Timer::expire(Event *)
+{
+   a_->timeout(1);
+}
+
+void Thp_Report_Timer::expire(Event *)
+{
+   a_->timeout(0);
+}
+
+void Report_Processing_Timer::expire(Event *)
+{
+   a_->timeout(1);
+}
+
+void Buff_Check_Timer::expire(Event *)
+{
+   a_->timeout(2);
+}
+
+void Pending_Timer::expire(Event *)
+{
+   a_->timeout(3);
+}
+
+TCM::TCM():BiConnector(), bs_(0), direction_(0), total_bits_(0), status_(0), cs_(0), am_(NULL), um_(NULL),
+THP_RT(this), RPT(this), BRT(this), PTAT(this)
+{
+
+   bind_time("THP_REPORT_INTERVAL_", &THP_REPORT_INTERVAL_);
+   bind("DOWNSWITCH_THRESHOLD_", &DOWNSWITCH_THRESHOLD_);
+   bind("DOWNSWITCH_TIMER_THRESHOLD_", &DOWNSWITCH_TIMER_THRESHOLD_);
+   bind("UL_RLC_BUF_UPSWITCH_THRESH_sRAB_", &UL_RLC_BUF_UPSWITCH_THRESH_sRAB_);
+   bind("DL_RLC_BUF_UPSWITCH_THRESH_sRAB_", &DL_RLC_BUF_UPSWITCH_THRESH_sRAB_);
+   bind_time("PENDING_TIME_AFTER_TRIGGER_", &PENDING_TIME_AFTER_TRIGGER_);
+   bind_time("BUFF_CHECK_INTERVAL_", &BUFF_CHECK_INTERVAL_);
+
+   BRT.resched(BUFF_CHECK_INTERVAL_);
+   THP_RT.resched(THP_REPORT_INTERVAL_);
+}
+
+int TCM::command(int argc, const char *const *argv)
+{
+   if (argc == 3) {
+      if (strcmp(argv[1], "CS") == 0) {
+         cs_ = (CS *) TclObject::lookup(argv[2]);
+         if (cs_ == NULL) {
+            return (TCL_ERROR);
+         }
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "BS") == 0) {
+         bs_ = atoi(argv[2]);
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "RLC-AM") == 0) {
+         am_ = (AM *) TclObject::lookup(argv[2]);
+         if (am_ == NULL) {
+            return (TCL_ERROR);
+         }
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "RLC-UM") == 0) {
+	um_ = (UM *) TclObject::lookup(argv[2]);
+	if (um_ == NULL) {
+	   return (TCL_ERROR);
+	}
+        return (TCL_OK);
+      }	
+   }
+   return (BiConnector::command(argc, argv));
+}
+
+void TCM::recv(Packet * p, Handler * callback)
+{
+
+   hdr_cmn    *ch = HDR_CMN(p);
+
+   total_bits_ = total_bits_ + (ch->size() * 8);
+   if (direction_ == dedicated) {
+      sendUp(p, 0);
+   } else if (direction_ == common) {
+      sendDown(p, 0);
+   } else {
+      drop(p);
+   }
+}
+
+void TCM::timeout(int tno)
+{
+   if (tno == 0) {
+      double throughput_bps = total_bits_ / THP_REPORT_INTERVAL_;
+
+      throughput_ = (int) throughput_bps / 1024;
+      if (((int) throughput_bps % 1024) > 512) {
+         throughput_++;
+      }
+      total_bits_ = 0;
+
+      if (throughput_ < DOWNSWITCH_THRESHOLD_) {
+         status_ = 1;
+      } else if (throughput_ > DOWNSWITCH_TIMER_THRESHOLD_) {
+         status_ = 2;
+      } else {
+         status_ = 0;
+      }
+
+      if (bs_) {
+         RPT.resched(0.000005);
+      }
+
+      THP_RT.resched(THP_REPORT_INTERVAL_);
+
+   } else if (tno == 1) {
+      cs_->timeout(0);
+   } else if (tno == 2) {
+     
+       int size = 0;
+     
+      // Added check for UM RLC support also
+      if (am_ != NULL) {
+        size =am_->buff_size() / 100;
+
+        if ((am_->buff_size() % 100) > 50) {
+          size++;
+        }
+	
+      } else if (um_ != NULL) {
+         size =um_->buff_size() / 100;
+
+	 if ((um_->buff_size() % 100) > 50) {
+		 size++;
+	 }
+      }
+	      
+      size = size * 100;
+      if (bs_) {
+         if (size > DL_RLC_BUF_UPSWITCH_THRESH_sRAB_) {
+            cs_->timeout(2);
+            PTAT.resched(PENDING_TIME_AFTER_TRIGGER_);
+         } else {
+            BRT.resched(BUFF_CHECK_INTERVAL_);
+         }
+      } else if (size > UL_RLC_BUF_UPSWITCH_THRESH_sRAB_) {
+         cs_->timeout(2);
+         PTAT.resched(PENDING_TIME_AFTER_TRIGGER_);
+      } else {
+         BRT.resched(BUFF_CHECK_INTERVAL_);
+      }
+
+   } else if (tno == 3) {
+      BRT.resched(BUFF_CHECK_INTERVAL_);
+   }
+}
+
+
+CS::CS():NsObject(), uplink_(0), downlink_(0), uplink_am_(NULL), downlink_am_(NULL), downlink_um_(NULL), uplink_um_(NULL),DS_T_sRab(this)
+{
+   bind_time("DOWNSWITCH_TIMER_sRAB_", &DOWNSWITCH_TIMER_sRAB_);
+   bind_bool("noSwitching_", &noSwitching_);
+}
+
+
+int CS::command(int argc, const char *const *argv)
+{
+   if (argc == 3) {
+      if (strcmp(argv[1], "uplink-tcm") == 0) {
+         uplink_ = (TCM *) TclObject::lookup(argv[2]);
+         if (uplink_ == NULL) {
+            return (TCL_ERROR);
+         }
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "downlink-tcm") == 0) {
+         downlink_ = (TCM *) TclObject::lookup(argv[2]);
+         if (downlink_ == NULL)
+            return (TCL_ERROR);
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "uplink-AM") == 0) {
+         uplink_am_ = (AM *) TclObject::lookup(argv[2]);
+         if (uplink_am_ == NULL) {
+            return (TCL_ERROR);
+         }
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "downlink-AM") == 0) {
+         downlink_am_ = (AM *) TclObject::lookup(argv[2]);
+         if (downlink_am_ == NULL) {
+            return (TCL_ERROR);
+         }
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "downlink-UM") == 0) {
+         downlink_um_ = (UM *) TclObject::lookup(argv[2]);
+         if (downlink_um_ == NULL) {
+            return (TCL_ERROR);
+         }
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "uplink-UM") == 0) {
+         uplink_um_ = (UM *) TclObject::lookup(argv[2]);
+         if (uplink_um_ == NULL) {
+            return (TCL_ERROR);
+         }
+         return (TCL_OK);
+      }
+   } else if (argc == 6) {
+      if (strcmp(argv[1], "rlc_DS_info") == 0) {
+         ds_node_tti_ = atof(argv[2]);
+         ds_node_bw_ = atof(argv[3]);
+         ds_bs_tti_ = atof(argv[4]);
+         ds_bs_bw_ = atof(argv[5]);
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "rlc_US_info") == 0) {
+         us_node_tti_ = atof(argv[2]);
+         us_node_bw_ = atof(argv[3]);
+         us_bs_tti_ = atof(argv[4]);
+         us_bs_bw_ = atof(argv[5]);
+         return (TCL_OK);
+      }
+   }
+   return (NsObject::command(argc, argv));
+}
+
+void CS::timeout(int type)
+{
+   if (type == 0) {
+      assert(uplink_ && downlink_);
+      if (uplink_->status() == 1 && downlink_->status() == 1
+          && DS_T_sRab.status() == TIMER_IDLE) {
+         DS_T_sRab.resched(DOWNSWITCH_TIMER_sRAB_ + 0.00001);
+      } else if ((uplink_->status() == 2 || downlink_->status() == 2)
+                 && DS_T_sRab.status() == TIMER_PENDING) {
+         DS_T_sRab.cancel();
+      }
+   } else if (type == 1) {
+      /* do you want to introduce a probability here?
+       * To simulate downswitch failures? */
+      if (noSwitching_) {
+         DS_T_sRab.resched(DOWNSWITCH_TIMER_sRAB_ + 0.00001);
+         return;
+      }
+      uplink_->direction() = common;
+      downlink_->direction() = common;
+
+      if ( uplink_am_ != NULL && downlink_am_ !=NULL ) {
+	uplink_am_->CSwitch(ds_node_bw_, ds_node_tti_);
+	downlink_am_->CSwitch(ds_bs_bw_, ds_bs_tti_);
+      } else if (uplink_um_ != NULL && downlink_um_ != NULL) {
+	uplink_um_->CSwitch(ds_node_bw_, ds_node_tti_);
+	downlink_um_->CSwitch(ds_bs_bw_, ds_bs_tti_);
+      }
+      
+/*		cout<<"downswitch at "<<Scheduler::instance().clock()<<endl; */
+      DS_T_sRab.resched(DOWNSWITCH_TIMER_sRAB_ + 0.00001);
+
+   } else if (type == 2) {
+      /* do you want to introduce a probability here?
+       * To simulate upswitch failures? */
+      if (noSwitching_) {
+         return;
+      }
+      uplink_->direction() = dedicated;
+      downlink_->direction() = dedicated;
+      if ( uplink_am_ != NULL && downlink_am_ !=NULL ) {
+	uplink_am_->CSwitch(us_node_bw_, us_node_tti_);
+	downlink_am_->CSwitch(us_bs_bw_, us_bs_tti_);
+      } else if (uplink_um_ != NULL && downlink_um_ != NULL) {
+	uplink_um_->CSwitch(us_node_bw_, us_node_tti_);
+	downlink_um_->CSwitch(us_bs_bw_, us_bs_tti_);
+      }
+/*		cout<<"upswitch at "<<Scheduler::instance().clock()<<endl; */
+   }
+}
diff -urN ns-2.30-orig/umts/tcs.h ns-2.30-eu112/umts/tcs.h
--- ns-2.30-orig/umts/tcs.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/tcs.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: tcs.h,v 1.1 2005/04/27 14:30:09 simon Exp $
+ */
+
+/*
+ * Code for Transport Channel Switching
+ */
+
+#ifndef ns_tcs_h
+#define ns_tcs_h
+
+#include "bi-connector.h"
+#include "timer-handler.h"
+#include "am.h"
+#include "um.h"
+
+#define	dedicated	0
+#define	common		1
+
+
+class CS;
+class TCM;
+
+class DownSwitch_Timer:public TimerHandler {
+public:
+   DownSwitch_Timer(CS * a):TimerHandler() {
+      a_ = a;
+} protected:
+   virtual void expire(Event * e);
+   CS         *a_;
+};
+
+
+class Thp_Report_Timer:public TimerHandler {
+public:
+   Thp_Report_Timer(TCM * a):TimerHandler() {
+      a_ = a;
+} protected:
+   virtual void expire(Event * e);
+   TCM        *a_;
+};
+
+class Report_Processing_Timer:public TimerHandler {
+public:
+   Report_Processing_Timer(TCM * a):TimerHandler() {
+      a_ = a;
+} protected:
+   virtual void expire(Event * e);
+   TCM        *a_;
+};
+
+class Buff_Check_Timer:public TimerHandler {
+public:
+   Buff_Check_Timer(TCM * a):TimerHandler() {
+      a_ = a;
+} protected:
+   virtual void expire(Event * e);
+   TCM        *a_;
+};
+
+class Pending_Timer:public TimerHandler {
+public:
+   Pending_Timer(TCM * a):TimerHandler() {
+      a_ = a;
+} protected:
+   virtual void expire(Event * e);
+   TCM        *a_;
+};
+
+
+class CS:   public NsObject {
+public:
+   CS();
+   virtual void timeout(int type);
+protected:
+   int         command(int argc, const char *const *argv);
+   void        recv(Packet *, Handler * callback = 0) {
+   } int       noSwitching_;
+   TCM        *uplink_;
+   TCM        *downlink_;
+   AM         *uplink_am_;
+   AM         *downlink_am_;
+   UM         *downlink_um_;
+   UM         *uplink_um_;
+   double      us_node_tti_;
+   double      us_node_bw_;
+   double      ds_node_tti_;
+   double      ds_node_bw_;
+   double      us_bs_tti_;
+   double      us_bs_bw_;
+   double      ds_bs_tti_;
+   double      ds_bs_bw_;
+   double      DOWNSWITCH_TIMER_sRAB_;
+   DownSwitch_Timer DS_T_sRab;
+};
+
+class TCM:  public BiConnector {
+public:
+   TCM();
+   virtual void timeout(int tno);
+   int         status() {
+      return status_;
+   } int      &direction() {
+      return direction_;
+   }
+   int        &totalBits() {
+      return total_bits_;
+   }
+ protected:
+   int         command(int argc, const char *const *argv);
+   void        recv(Packet *, Handler * callback = 0);
+
+   int         bs_;
+   int         direction_;
+   int         total_bits_;
+   int         throughput_;
+   int         status_;
+   CS         *cs_;
+   AM         *am_;
+   UM         *um_;
+
+   double      THP_REPORT_INTERVAL_;
+   double      DOWNSWITCH_THRESHOLD_;
+
+   double      DOWNSWITCH_TIMER_THRESHOLD_;
+
+   int         UL_RLC_BUF_UPSWITCH_THRESH_sRAB_;
+   int         DL_RLC_BUF_UPSWITCH_THRESH_sRAB_;
+
+   double      PENDING_TIME_AFTER_TRIGGER_;
+   double      BUFF_CHECK_INTERVAL_;
+
+   Thp_Report_Timer THP_RT;
+   Report_Processing_Timer RPT;
+   Buff_Check_Timer BRT;
+   Pending_Timer PTAT;
+
+};
+
+#endif
diff -urN ns-2.30-orig/umts/um-hs.cc ns-2.30-eu112/umts/um-hs.cc
--- ns-2.30-orig/umts/um-hs.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/um-hs.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,696 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: um-hs.cc,v 1.1 2005/04/27 14:30:10 simon Exp $
+ */
+
+
+// UM-HS is basically AM-HS with all the acknowledgements and retransmissions
+// taken out.
+
+#include "um-hs.h"
+#include "mac.h"
+#include "flags.h"
+#include "random.h"
+#include "address.h"
+#include "hsdpalink.h"
+#include "timer-handler.h"
+
+// These variables are used as 'super-globals', in this way the UM-HS object
+// and the MAC-hs object at the BS can be reached.
+
+extern RLC_HS *rlc_address;     //= this;
+extern HsdpaMac *mac_address;   //defined in hsdpalink.cc
+
+static class UM_HSRlcClass:public TclClass {
+public:
+   UM_HSRlcClass():TclClass("UMTS/RLC/UMHS") {
+   } TclObject *create(int, const char *const *) {
+      return (new UM_HS);
+   }
+}
+
+class_um_hs;
+
+UM_HS::UM_HS():RLC_HS(), creditTimer_(this, RLC_TIMER_CREDIT)
+{
+   rlc_address = this;
+
+   bind("macDA_", &macDA_);
+   bind("win_", &win_);
+   bind_time("temp_pdu_timeout_time_", &tempPDUTimeOutTime_);
+   bind("credit_allocation_interval_", &creditAllocationInterval_);
+   bind("flow_max_", &flowMax_);
+   bind("priority_max_", &priorityMax_);
+   bind("buffer_level_max_", &bufferLevelMax_);
+   bind("payload_", &payloadSize_);
+   bind_time("TTI_", &TTI_);
+   bind("length_indicator_", &length_indicator_);
+   bind("min_concat_data_", &min_concat_data_);
+
+   // Calculate the size in bytes of Length Indicator including the
+   // Extention bit. If a PDU consists of multiple parts, for each
+   // part these two fields are added to the header. If the PDU consists
+   // of only one part, these fields are omitted (9.2.1.4 + 9.2.2.5 from
+   // 3GPP TS 25.322 v5.6.0).
+   lengthIndicatorSize_ = ((length_indicator_ + 1) / 8);
+
+   // credit_allocation_interval_ is specified in numbers of TTIs, for our
+   // timer, we need it in seconds.
+   creditAllocationTimeoutInterval_ = TTI_ * creditAllocationInterval_;
+
+   // Initialize the vectors for the Flow Information and Transmission Buffers
+   for (int i = 0; i < flowMax_; i++) {
+      um_flow_information *temp = new um_flow_information(this, i);
+
+      for (int j = 0; j < priorityMax_; j++) {
+         umtsQueue  *temp2 = new umtsQueue;
+
+         temp->transmissionBuffer_.push_back(temp2);
+      }
+      flowInfo_.push_back(temp);
+   }
+
+   // schedule credit allocation timer for the first time
+   creditTimer_.sched(creditAllocationTimeoutInterval_);
+
+}
+
+
+int UM_HS::command(int argc, const char *const *argv)
+{
+   if (argc == 2) {
+      Tcl & tcl = Tcl::instance();
+      if (strcmp(argv[1], "TTI") == 0) {
+         tcl.resultf("%f", TTI_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "BW") == 0) {
+         tcl.resultf("%f", bandwidth_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "start_TTI") == 0) {
+         // do nothing (so ignore this methodcall, the timers are started by the
+         // constructor)
+         return TCL_OK;
+      }
+   } else if (argc == 3) {
+      if (strcmp(argv[1], "macDA") == 0) {
+         int nodeID = Address::instance().str2addr(argv[2]);
+
+         // The node-ids of the UEs start at 2, so decrease the node-id by two
+         // to get the flow-id
+         flowInfo_.at(nodeID - 2)->macDA_ = nodeID;
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "addr") == 0) {
+         address_ = Address::instance().str2addr(argv[2]);
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "daddr") == 0) {
+         int nodeID = Address::instance().str2addr(argv[2]);
+
+         // The node-ids of the UEs start at 2, so decrease the node-id by two
+         // to get the flow-id
+         flowInfo_.at(nodeID - 2)->d_address_ = nodeID;
+         return (TCL_OK);
+      }
+   }
+   int returnvalue = LL::command(argc, argv);
+
+
+   return returnvalue;
+}
+
+void UM_HS::recv(Packet * p, Handler * h)
+{
+
+
+   hdr_cmn    *ch = HDR_CMN(p);
+
+   // If the direction is up, we don't have to change anything, and the packet
+   // can be processed.
+   if (ch->direction() == hdr_cmn::UP) {
+      hdr_rlc    *llh = hdr_rlc::access(p);
+      int flowID = hdr_ip::access(p)->flowid();
+
+
+      if (llh->dst() != address_ || ch->error() > 0) {
+         // The packet was meant for another UE, or it contained errors. In
+         // both cases it will be dropped.
+         Packet::free(p);
+         return;
+      }
+      // Check the type op packets
+      if (llh->lltype() == RLC_DATA) {
+         // We only pass the last PDU of an SDU. The rest of the PDUs are not
+         // needed for the reassembly and can be freed.
+
+         int flowID = hdr_ip::access(p)->flowid();
+
+         hdr_tcp    *tcph = hdr_tcp::access(p);
+         hdr_rlc    *llh = hdr_rlc::access(p);
+         int temp_sdu = tcph->seqno();
+         int temp_seqno = llh->seqno();
+         int temp_segment = llh->segment();
+
+
+         if (temp_seqno == llh->eopno()) {
+            // The packet is the last PDU of an SDU. Now, check whether the
+            // complete SDU has been received. If so, pass the SDU up. In either
+            // case, the next expected packet will be the first PDU of the next
+            // SDU.
+            if (flowInfo_.at(flowID)->nextExpectedSeqno_ == temp_seqno
+                && flowInfo_.at(flowID)->nextExpectedSDU_ == temp_sdu
+                && flowInfo_.at(flowID)->errorInSDU_ == 0) {
+               makeSDU(p);
+            } else {
+               Packet::free(p);
+            }
+            flowInfo_.at(flowID)->errorInSDU_ = 0;
+            flowInfo_.at(flowID)->nextExpectedSDU_ = temp_sdu + 1;
+            flowInfo_.at(flowID)->nextExpectedSeqno_ = temp_seqno + 1;
+         } else {
+            // The packet is not the last PDU of an SDU. When the packet is the
+            // expected packet, increase the next expected packet. If not, the
+            // next packet is the next packet after this one. In that case,
+            // set errorInSDU so that this current SDU will not be passed up,
+            // unless this is the first segment of the SDU. In that case, the
+            // missed PDU didn't belong to this SDU but to the previous one.
+            if (flowInfo_.at(flowID)->nextExpectedSeqno_ == temp_seqno) {
+               flowInfo_.at(flowID)->nextExpectedSeqno_++;
+            } else {
+               flowInfo_.at(flowID)->nextExpectedSDU_ = temp_sdu;
+               flowInfo_.at(flowID)->nextExpectedSeqno_ = temp_seqno + 1;
+               if (temp_segment != 0) {
+                  flowInfo_.at(flowID)->errorInSDU_++;
+               }
+            }
+            Packet::free(p);
+         }
+
+      } else {
+         // In case the type of the packet is something else, just drop it.
+         drop(p);               // Unknown type
+      }
+      return;
+   } else {
+      ch->direction() = hdr_cmn::DOWN;
+      sendDown(p);
+   }
+
+}
+
+int UM_HS::enqueInBackOfTransmissionBuffer(Packet * p)
+{
+
+   int r_value = 0;
+
+
+   int flowID = hdr_ip::access(p)->flowid();
+   int priority = hdr_ip::access(p)->prio();
+
+
+
+   if ((flowInfo_.at(flowID)->transmissionBuffer_.at(priority)->length())
+       >= bufferLevelMax_) {
+      drop(p);
+   } else {
+      flowInfo_.at(flowID)->transmissionBuffer_.at(priority)->enque(p);
+      r_value = 1;
+   }
+
+
+   return r_value;
+}
+
+
+
+//---------------------------
+// sendDown processes a SDU into PDUs for transmission to MAC-HS
+// if possible, waiting temporary packets are filled up.
+//---------------------------
+
+void UM_HS::sendDown(Packet * p)
+{
+
+   // First check whether the SDU fits into the transmission buffer completely
+
+   int numPDUs =
+         (int) ceil((double) hdr_cmn::access(p)->size() /
+                    (double) payloadSize_);
+
+   if (numPDUs + 1 +
+       flowInfo_.at(hdr_ip::access(p)->flowid())->transmissionBuffer_.
+       at(hdr_ip::access(p)->prio())->length()
+       >= bufferLevelMax_) {
+      Packet::free(p);
+      return;
+   }
+
+   int segment = 0;
+
+   // First check whether there is still a not-finished PDU available that can
+   // be used for concatenation.
+   handleTemporaryPacket(p);
+
+   if (hdr_rlc::access(p)->segment() == 0) {
+      // There was something that could be concatenated, and thus the first
+      // segment of the packet was already sent, so continue with the next.
+      segment++;
+   }
+
+   while (p != NULL) {
+      // Each loop the front of the SDU is removed and send in a PDU. This
+      // results in a smaller and smaller SDU, until at some point in time
+      // it is completely gone. In that case p equals to NULL and the
+      // complete SDU is segmented.
+
+      int concat_data = 0;
+      bool close_PDU = false;
+      int padding = 0;
+      bool force_length_indicator = false;
+      Packet     *c;
+
+      int p_size = hdr_cmn::access(p)->size();
+
+      close_PDU = p_size <= payloadSize_;
+      force_length_indicator = p_size < payloadSize_;
+
+      if (p_size <= (payloadSize_ - lengthIndicatorSize_)) {
+         // decide whether the remaining data is too big too keep
+         // in which case we send it on with padding
+         concat_data = payloadSize_ - p_size - 2 * lengthIndicatorSize_;
+         if (concat_data < min_concat_data_) {
+            concat_data = 0;
+            padding = payloadSize_ - p_size - lengthIndicatorSize_;
+         } else {
+            padding = 0;
+         }
+      }
+
+      if (close_PDU) {
+         // reuse packet p
+         c = p;
+         p = NULL;
+      } else {
+         // copy p's data into c and force concat_data and padding to 0
+         concat_data = 0;
+         padding = 0;
+         c = p->copy();
+      }
+
+
+      //initialise shortcuts to c's header info
+      hdr_cmn    *c_ch = HDR_CMN(c);
+      hdr_rlc    *c_llh = hdr_rlc::access(c);
+      hdr_ip     *c_iph = hdr_ip::access(c);
+      int flowID = c_iph->flowid();
+      hdr_cmn    *p_ch = NULL;
+      hdr_ip     *p_iph = NULL;
+
+      if (p != NULL) {
+         p_ch = HDR_CMN(p);
+         p_iph = hdr_ip::access(p);
+      }
+
+      c_llh->lptype() = c_ch->ptype();
+      c_llh->lerror_ = c_ch->error();
+      c_llh->lts_ = c_ch->timestamp();
+      c_llh->segment() = segment;
+      segment++;
+
+      if (close_PDU) {
+
+         if (flowInfo_.at(flowID)->SDU_size_ > 0) {
+            c_llh->lsize_ = flowInfo_.at(flowID)->SDU_size_;
+         } else {
+            c_llh->lsize_ = c_ch->size();
+         }
+
+         flowInfo_.at(flowID)->SDU_size_ = -1;
+
+      } else if (flowInfo_.at(flowID)->SDU_size_ < 0) {
+         assert(p != NULL);
+         flowInfo_.at(flowID)->SDU_size_ = hdr_cmn::access(p)->size();
+      }
+
+      c_llh->lltype() = RLC_DATA;
+      c_llh->seqno() = flowInfo_.at(flowID)->seqno_;
+      flowInfo_.at(flowID)->seqno_++;
+      c_llh->dst() = flowInfo_.at(flowID)->d_address_;
+      c_llh->src() = address_;
+      c_llh->lengthInd_ = 0;
+
+      if (close_PDU) {
+         // c_llh->eopno_ needs to be set to c_llh->seqno_. However, at this
+         // moment the seqno is not known yet. So, set it to EOPNO_TO_SEQNO
+         // and check when seqno is set whether eopno is EOPNO_TO_SEQNO. If this
+         // is the case eopno can be replaced by seqno.
+         c_llh->eopno_ = EOPNO_TO_SEQNO;
+      } else {
+         c_llh->eopno_ = EOPNO_NOT_EOP;
+      }
+
+      if (concat_data || padding || force_length_indicator) {
+         c_llh->lengthInd_++;
+      }
+
+      if (close_PDU) {
+         c_llh->payload_[PAYLOAD_FLD1] = c_ch->size();
+      } else {
+         if (force_length_indicator) {
+            c_llh->payload_[PAYLOAD_FLD1] = payloadSize_ - lengthIndicatorSize_;
+         } else {
+            c_llh->payload_[PAYLOAD_FLD1] = payloadSize_;
+         }
+      }
+      c_llh->payload_[PAYLOAD_FLD2] = 0;
+      c_llh->payload_[PAYLOAD_FLD3] = 0;
+
+      c_llh->padding_ = padding; //padding will always have the correct value here
+
+      // WTF? this is really ugly, bad things will happen here!
+      char       *mh = (char *) c->access(hdr_mac::offset_);
+      struct hdr_mac *c_dh = (struct hdr_mac *) mh;
+
+      c_ch->ptype() = PT_UM;
+      c_dh->macDA_ = flowInfo_.at(flowID)->macDA_;
+      c_dh->macSA_ = -1;
+      c_dh->hdr_type() = ETHERTYPE_RLC;
+      c_ch->timestamp() = Scheduler::instance().clock();
+
+      // Do we have space left over for concatenation?
+      if (close_PDU) {
+         if (concat_data) {
+            // Store the current packet and do not send it down.
+            // Because this is also the last part of the SDU we can
+            // stop this method.
+            c_llh->lengthInd_++;
+
+            StoreTemporaryPacket(c, concat_data);
+            break;              //exit while loop
+         }
+      } else {
+         // reduce the size of the SDU by an amount of the
+         // payload that will be sent in this PDU.
+         p_ch->size() = p_ch->size() - c_llh->payload_[PAYLOAD_FLD1];
+      }
+
+      assert(c_ch->error() == 0);
+
+
+      c_ch->size() = payloadSize_;
+
+
+      //----------
+      if (enqueInBackOfTransmissionBuffer(c) == 0) {
+      } else {
+      }
+
+   }
+
+
+}
+
+// This method is called when a PDU is created that is not full, and just stores
+// the PDU into a vector that will be inspected
+
+void UM_HS::StoreTemporaryPacket(Packet * p, int concat_data)
+{
+
+
+   temporaryPacket *temp = new temporaryPacket(this);
+
+   temp->p = p;
+   temp->concat_data = concat_data;
+   // We can't wait forever, because then we have a problem at the end of a
+   // burst of traffic: then the last PDU won't be send, causing timeouts and
+   // retransmissions. So, we do want to send the incomplete packet anyway
+   // at some point in time.
+   temp->tempPDUTimer.sched(tempPDUTimeOutTime_);
+   temporaryPackets_.push_back(temp);
+}
+
+
+void UM_HS::handleTemporaryPacket(Packet * p)
+{
+
+
+   if (p == NULL) {
+      return;
+   }
+   // get the flow-id and priority for the current PDU
+   int flowID = hdr_ip::access(p)->flowid();
+   int priority = hdr_ip::access(p)->prio();
+
+
+   // Search all current temporary PDUs to find a temporary PDU with
+   // the same flow-id and priority
+   for (unsigned int i = 0; i < temporaryPackets_.size(); i++) {
+
+
+      if (hdr_ip::access(temporaryPackets_.at(i)->p)->flowid() == flowID
+          && hdr_ip::access(temporaryPackets_.at(i)->p)->prio() == priority) {
+         // We have found one
+
+         // Fill the temporary PDU with data from the new SDU, and delete that
+         // part of the SDU. Then store the temporary PDU in the Transmission
+         // and Retransmission Buffers and return the remaining part of the SDU.
+
+         // Concatenation (3GPP TS 25.301 5.3.2.2): If the contents of an RLC
+         // SDU cannot be carried by one RLC PDU, the first segment of the next
+         // RLC SDU may be put into the RLC PDU in concatenation with the last
+         // segment of the previous RLC SDU.
+
+         if (hdr_cmn::access(p)->size() > payloadSize_) {
+
+            hdr_rlc::access(temporaryPackets_.at(i)->p)->payload_[1] =
+                  temporaryPackets_.at(i)->concat_data;
+            // this variable was previously set in makePDU
+            flowInfo_.at(hdr_ip::access(p)->flowid())->SDU_size_ =
+                  hdr_cmn::access(p)->size();
+            hdr_cmn::access(p)->size() =
+                  hdr_cmn::access(p)->size() -
+                  temporaryPackets_.at(i)->concat_data;
+
+            // Set the segemnt to 0, in this way it is known that segmentation
+            // did occur.
+            hdr_rlc::access(p)->segment() = 0;
+
+         } else {
+
+            hdr_rlc::access(temporaryPackets_.at(i)->p)->lengthInd_--;
+            hdr_rlc::access(temporaryPackets_.at(i)->p)->padding_ =
+                  temporaryPackets_.at(i)->concat_data + lengthIndicatorSize_;
+         }
+         enqueInBackOfTransmissionBuffer(temporaryPackets_.at(i)->p);
+
+         // Now the temporary PDU has been sent, delete the timer
+         // so that the timeout will not occur anymore.
+         temporaryPackets_.at(i)->tempPDUTimer.cancel();
+         temporaryPackets_.erase((temporaryPackets_.begin() + i));
+         return;
+
+      }
+   }
+}
+
+
+void UM_HS::timeout(int tno, int flowID)
+{
+   vector < int >temp_vect;
+
+
+   switch (tno) {
+     case RLC_TIMER_TEMP_PDU:
+        // Walk through all temporary PDUs and check whether their
+        // timeout-time is the same as the current time or lies in the
+        // past (actually, this shouldn't happen). If that is the case
+        // send those PDUs and remove them from the vector.
+        for (unsigned int i = 0; i < temporaryPackets_.size(); i++) {
+
+           // For performance reasons it might be a good idea to
+           // not only select the temporary PDUs that have to be sent
+           // now, but also the PDUs that are due within a small
+           // period in time, so that timeouts do not occur that
+           // often anymore.
+           if (Scheduler::instance().clock() >=
+               temporaryPackets_.at(i)->tempPDUTimer.timeOfExpiry()) {
+              // We have found one
+
+              // Before we stored the temporary PDU in the
+              // vector, we set the number of Length Indicators
+              // and the number of bytes that could be
+              // concatenated. Because we are not concatenating,
+              // but padding we need one Length Indicator less,
+              // thus we have to pad more.
+              hdr_rlc::access(temporaryPackets_.at(i)->p)->lengthInd_--;
+              hdr_rlc::access(temporaryPackets_.at(i)->p)->padding_ =
+                    temporaryPackets_.at(i)->concat_data + lengthIndicatorSize_;
+              enqueInBackOfTransmissionBuffer(temporaryPackets_.at(i)->p);
+              temporaryPackets_.erase((temporaryPackets_.begin() + i));
+              i--;              // otherwise the next temporary packet will be skipped
+           }
+        }
+        break;
+     case RLC_TIMER_CREDIT:
+        // Send a credit allocation request to the MAC-hs. And reschedule
+        // the timer
+
+        // Create a vector with the length of the Transmission Buffers, and
+        // send this vector to the MAC-hs.
+
+        //Note: Buffers indexed: f1p1,f2p1,f3p1,f1p2,f2p2,f3p2,f1p3...
+
+
+        for (int i = 0; i < priorityMax_; i++) {
+           for (int j = 0; j < flowMax_; j++) {
+              temp_vect.push_back(flowInfo_.at(j)->transmissionBuffer_.at(i)->
+                                  length());
+           }
+        }
+
+        mac_address->cred_alloc(&temp_vect);
+
+
+        // Reschedule
+        creditTimer_.resched(creditAllocationTimeoutInterval_);
+        break;
+     default:
+
+        break;
+   }
+
+}
+
+void UM_HS::completePDU(Packet * p)
+{
+
+
+   hdr_rlc    *llh = hdr_rlc::access(p);
+   int flowID = hdr_ip::access(p)->flowid();
+
+   // If the packet is transmitted for the first time, set the sequence number
+   // and possibly the eop number.
+   if (llh->seqno() == -1) {
+      llh->seqno() = flowInfo_.at(flowID)->seqno_;
+      flowInfo_.at(flowID)->seqno_++;
+      if (llh->eopno() == EOPNO_TO_SEQNO) {
+         llh->eopno() = llh->seqno();
+      }
+   }
+   return;
+}
+
+// This method is called by the MACHS to update the current credit allocation
+// values. After that, schedule the first packet.
+
+void UM_HS::credit_update(vector < int >new_rlc_credits)
+{
+
+
+
+   vector < int >highestPriority;
+   int        *highestNonEmptyQueue = new int;
+
+   // Check in what PDU the poll bit should be set. It should be set in the
+   // last packet that will be sent for each flow.
+   for (int i = 0; i < flowMax_; i++) {
+      *highestNonEmptyQueue = 0;
+      for (int j = 0; j < priorityMax_; j++) {
+         if (new_rlc_credits.at(i * priorityMax_ + j) > 0) {
+            *highestNonEmptyQueue = j;
+         }
+      }
+      highestPriority.push_back(*highestNonEmptyQueue);
+   }
+   // For each buffer, transmit the number of PDUs defined in the credit
+   // allocation vector.
+   for (int i = 0; i < priorityMax_; i++) {
+      for (int j = 0; j < flowMax_; j++) {
+         for (int k = 0; k < new_rlc_credits.at(i * flowMax_ + j); k++) {
+            //Note: Buffers indexed: f1p1,f2p1,f3p1,f1p2,f2p2,f3p2,f1p3...
+
+            Packet     *p;
+
+
+            // The next sequence number will be inside the transmission
+            // window, so we can send the first packet.
+            p = flowInfo_.at(j)->transmissionBuffer_.at(i)->deque();
+
+
+            if (p != NULL) {
+
+
+               // Check whether the packet that has been chosen
+               // has some space left that can be used for
+               // biggybacking.
+               completePDU(p);
+
+               // Actually send the packet down.
+               downtarget_->recv(p);
+
+               // Increase the number of PDUs sent. This is used for adding the
+               // poll bit each poll_pdu_ packets.
+            } else {
+               // The number of packets available in the queue was smaller than
+               // the maximum number of packets that we were allowed to send to
+               // the Mac-hs.
+               break;
+            }
+         }
+      }
+   }
+}
+
+
+void UM_HS::makeSDU(Packet * p)
+{
+   hdr_cmn    *ch;
+   hdr_rlc    *llh;
+
+   assert(p);
+   ch = HDR_CMN(p);
+   llh = hdr_rlc::access(p);
+
+   ch->ptype() = llh->lptype();
+   ch->error() = llh->lerror();
+   ch->timestamp() = llh->lts();
+   ch->size() = llh->lsize();
+
+   uptarget_ ? sendUp(p) : Packet::free(p);
+}
+
+
diff -urN ns-2.30-orig/umts/um-hs.h ns-2.30-eu112/umts/um-hs.h
--- ns-2.30-orig/umts/um-hs.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/um-hs.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: um-hs.h,v 1.5 2004/01/30 09:16:49 wtdavid Exp $
+ */
+
+#ifndef ns_um_hs_h
+#define ns_um_hs_h
+
+#include "rlc.h"
+#include "umts-timers.h"
+#include "umts-queue.h"
+#include "umts-headers.h"
+#include <vector>
+
+#define MWS 4096             /* max window size */
+#define MWM (MWS-1)          /* The "win_" parameter, representing the RLC window,
+                                 * should be less than equal to MWM. */
+
+#define EOPNO_NOT_EOP -1
+#define EOPNO_TO_SEQNO -2
+
+#define PAYLOAD_FLD1 0
+#define PAYLOAD_FLD2 1
+#define PAYLOAD_FLD3 2
+
+
+
+class UM_HS;
+
+class temporaryPacket {
+public:
+   temporaryPacket(RLC * rlc):tempPDUTimer(rlc, RLC_TIMER_TEMP_PDU) {
+   } Packet   *p;
+   int         concat_data;
+   UmtsTimer   tempPDUTimer;
+};
+
+class um_flow_information {
+public:
+   um_flow_information(UM_HS * umhs, int flowID):nextExpectedSDU_(0),
+         nextExpectedSeqno_(0), nextExpectedSegment_(0), errorInSDU_(0),
+         seqno_(0), send_status_(0), SDU_size_(0), maxseq_(-1), highest_ack_(0),
+         maxseen_(0), next_(0), d_address_(0), macDA_(0) {
+   } vector <  umtsQueue * >transmissionBuffer_;
+
+   // For our Transmission Buffer we use a vector of rlcQueue, for each
+   // flow-id and priority-pair one queue exists.
+
+   int         nextExpectedSDU_;
+   int         nextExpectedSeqno_;
+   int         nextExpectedSegment_;
+   int         errorInSDU_;
+
+   int         seqno_;
+
+   int         send_status_;
+   int         SDU_size_;       // stores the original size of the SDU when a part already
+
+   // was concatenated
+
+   int         maxseq_;         // highest seqno transmitted so far
+   int         highest_ack_;    // highest ack recieved by sender
+   int         maxseen_;        // max PDU (seqno)number seen by receiver
+   int         next_;           // next PDU expected by reciever
+
+   int         d_address_;      // destination address of this RLC Entity
+   int         macDA_;          // mac destination address for packets created by this RLC
+
+   // Entity
+
+   umtsQueue   sduB_;
+};
+
+class UM_HS:public RLC_HS {
+public:
+   UM_HS();
+   virtual void recv(Packet *, Handler *);
+   int         command(int, const char *const *);
+   void        credit_update(vector < int >new_rlc_credits);
+   void        timeout(int tno, int flowID = -1);
+protected:
+   int         enqueInBackOfTransmissionBuffer(Packet * p);
+   void        sendDown(Packet * p);
+   void        StoreTemporaryPacket(Packet * p, int concat_data);
+   void        handleTemporaryPacket(Packet * p);
+   void        completePDU(Packet * p);
+   void        makeSDU(Packet * p);
+
+               vector < um_flow_information * >flowInfo_;
+   // For each flow information has to be kept. All this information is kept in
+   // this struct.
+
+   int         lengthIndicatorSize_;
+   // The size of the Length indicator + the
+   // extention bit. The size is in bytes. The
+   // size is 1 or 2 bytes depending on the size
+   // of the PDUs.
+
+   // parameters of the object, set through TCL
+
+   int         win_;
+   // defines the RLC Window Size, which is the amount of packets that can be
+   // sent after the last acknowledged packet.
+
+   int         flowMax_;
+   // The maximum number of flows
+
+   int         priorityMax_;
+   // The maximum number of priorities
+
+   int         bufferLevelMax_;
+   // The maximum number of PDUs for each flow-id and
+   // priority pair in the Transmission Buffer.
+
+   int         creditAllocationInterval_;
+   // The number of TTIs between a new
+   // credit allocation.
+
+   double      tempPDUTimeOutTime_;
+   // When a PDU is constructed that has some
+   // space left, the PDU is stored in the vector
+   // temporaryPackets_. A timeout will be set
+   // to ensure that when no further SDU arrives
+   // with the same flow-id and priority, the
+   // not-full PDU will be sent and will not
+   // wait indefinitely.
+
+               vector < temporaryPacket * >temporaryPackets_;
+   // In this vector Temporary PDUs are stored. These are PDUs that a not
+   // completely full, and they can be possibly concatenated with a part of
+   // a new SDU. However, this concatenation should be done quick enough,
+   // otherwise timeouts and unnesessary delays may occur. So, a timer will
+   // be set, when the concatenation can be done before the timer times out,
+   // the PDU will be concatenated with a part of a new SDU. When the timer
+   // times out, the Temporary Packet is padded and sent without concatenation.
+
+   UmtsTimer   creditTimer_;
+   // This timer is used for the timout once every
+   // creditAllocationTimeoutInterval_. Then the
+   // RLC will start a new credit allocation.
+
+   double      creditAllocationTimeoutInterval_;
+   // = TTI_ * credit_allocation_interval_
+
+   double      overhead_;       // Time that is needed to contruct SDUs
+
+   int         payloadSize_;    // user data per DATA PDU
+   double      TTI_;
+
+   int         length_indicator_;
+   int         min_concat_data_;
+
+   int         address_;        // address of this RLC Entity
+
+};
+
+#endif
diff -urN ns-2.30-orig/umts/um.cc ns-2.30-eu112/umts/um.cc
--- ns-2.30-orig/umts/um.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/um.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: um.cc,v 1.1 2005/04/27 14:30:10 simon Exp $
+ */
+
+// UM is basically UM with all the support for multiple flows taken out. Also,
+// the credit allocation algorithm is replaced by a simple 'send-x-PDUs-per-TTI'
+// algorithm.
+
+#include "um.h"
+#include "mac.h"
+#include "flags.h"
+#include "random.h"
+#include "address.h"
+#include <iostream>
+
+int hdr_rlc::offset_;
+
+static class RLCHeaderClass:public PacketHeaderClass {
+public:
+   RLCHeaderClass():PacketHeaderClass("PacketHeader/RLC", sizeof(hdr_rlc)) {
+      bind_offset(&hdr_rlc::offset_);
+}}
+class_rlchdr;
+
+static class UMRlcClass:public TclClass {
+public:
+   UMRlcClass():TclClass("UMTS/RLC/UM") {
+   } TclObject *create(int, const char *const *) {
+      return (new UM());
+      return (NULL);
+   }
+}
+
+class_um;
+
+UM::UM():RLC(), temporaryPacket_(this), nextExpectedSDU_(0), nextExpectedSeqno_(0),
+nextExpectedSegment_(0), errorInSDU_(0), seqno_(0), send_status_(0),
+SDU_size_(0), maxseq_(-1), highest_ack_(0), maxseen_(0), next_(0),
+d_address_(0), macDA_(0), tti_timer_(this, RLC_TIMER_TTI)
+{
+   bind("win_", &win_);
+   bind_time("temp_pdu_timeout_time_", &tempPDUTimeOutTime_);
+   bind("buffer_level_max_", &bufferLevelMax_);
+   bind("payload_", &payloadSize_);
+   bind_time("TTI_", &TTI_);
+   bind("length_indicator_", &length_indicator_);
+   bind("min_concat_data_", &min_concat_data_);
+   bind("bandwidth_", &bandwidth_);
+   bind("macDA_", &macDA_);
+
+   // Calculate the size in bytes of Length Indicator including the
+   // Extention bit. If a PDU consists of multiple parts, for each
+   // part these two fields are added to the header. If the PDU consists
+   // of only one part, these fields are omitted (9.2.1.4 + 9.2.2.5 from
+   // 3GPP TS 25.322 v5.6.0).
+   lengthIndicatorSize_ = ((length_indicator_ + 1) / 8);
+   temporaryPacket_.p = NULL;
+
+   tti_timer_.sched(TTI_ - 0.001);
+
+}
+
+
+int UM::command(int argc, const char *const *argv)
+{
+   if (argc == 2) {
+      Tcl & tcl = Tcl::instance();
+      if (strcmp(argv[1], "TTI") == 0) {
+         tcl.resultf("%f", TTI_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "BW") == 0) {
+         tcl.resultf("%f", bandwidth_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "start_TTI") == 0) {
+         // do nothing (so ignore this methodcall, the timers are started by the
+         // constructor)
+         return TCL_OK;
+      }
+   } else if (argc == 3) {
+      if (strcmp(argv[1], "macDA") == 0) {
+         int nodeID = Address::instance().str2addr(argv[2]);
+
+         macDA_ = nodeID;
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "addr") == 0) {
+         address_ = Address::instance().str2addr(argv[2]);
+         return (TCL_OK);
+      } else if (strcmp(argv[1], "daddr") == 0) {
+         int nodeID = Address::instance().str2addr(argv[2]);
+
+         d_address_ = nodeID;
+         return (TCL_OK);
+      }
+   }
+   int returnvalue = LL::command(argc, argv);
+
+
+   return returnvalue;
+}
+
+void UM::recv(Packet * p, Handler * h)
+{
+
+
+   hdr_cmn    *ch = HDR_CMN(p);
+
+   // If the direction is up, we don't have to change anything, and the packet
+   // can be processed.
+   if (ch->direction() == hdr_cmn::UP) {
+      hdr_rlc    *llh = hdr_rlc::access(p);
+
+
+      if (llh->dst() != address_ || ch->error() > 0) {
+         // The packet was meant for another UE, or it contained errors. In
+         // both cases it will be dropped.
+         Packet::free(p);
+         return;
+      }
+      // Check the type op packets
+      if (llh->lltype() == RLC_DATA) {
+         // We only pass the last PDU of an SDU. The rest of the PDUs are not
+         // needed for the reassembly and can be freed.
+
+         hdr_tcp    *tcph = hdr_tcp::access(p);
+         hdr_rlc    *llh = hdr_rlc::access(p);
+         int temp_sdu = tcph->seqno();
+         int temp_seqno = llh->seqno();
+         int temp_segment = llh->segment();
+
+
+         if (temp_seqno == llh->eopno()) {
+            // The packet is the last PDU of an SDU. Now, check whether the
+            // complete SDU has been received. If so, pass the SDU up. In either
+            // case, the next expected packet will be the first PDU of the next
+            // SDU.
+            if (nextExpectedSeqno_ == temp_seqno && nextExpectedSDU_ == temp_sdu
+                && errorInSDU_ == 0) {
+               makeSDU(p);
+            } else {
+               Packet::free(p);
+            }
+            errorInSDU_ = 0;
+            nextExpectedSDU_ = temp_sdu + 1;
+            nextExpectedSeqno_ = temp_seqno + 1;
+         } else {
+            // The packet is not the last PDU of an SDU. When the packet is the
+            // expected packet, increase the next expected packet. If not, the
+            // next packet is the next packet after this one. In that case,
+            // set errorInSDU so that this current SDU will not be passed up,
+            // unless this is the first segment of the SDU. In that case, the
+            // missed PDU didn't belong to this SDU but to the previous one.
+            if (nextExpectedSeqno_ == temp_seqno) {
+               nextExpectedSeqno_++;
+            } else {
+               nextExpectedSDU_ = temp_sdu;
+               nextExpectedSeqno_ = temp_seqno + 1;
+               if (temp_segment != 0) {
+                  errorInSDU_++;
+               }
+            }
+            Packet::free(p);
+         }
+
+      } else {
+         // In case the type of the packet is something else, just drop it.
+         drop(p);               // Unknown type, inclusing Positive Acknowledgements
+      }
+      return;
+   } else {
+      // We think that this should always be the case, so why set it again? For
+      // testing purposes we should replace the following line by an assert
+      // statement to check it.
+      ch->direction() = hdr_cmn::DOWN;
+      sendDown(p);
+   }
+
+}
+
+//----------------------------------------------------------------
+//enquePacket
+//
+//if possible (i.e. buffers are not full) enqueue packet in both
+// transmission and re-transmissionbuffer.
+// return 1 after succesfull enqueing
+// if not possible, return 0
+int UM::enquePacket(Packet * p)
+{
+
+   int r_value = 0;
+
+
+   r_value = enqueInBackOfTransmissionBuffer(p);
+
+
+   return r_value;
+}
+
+int UM::enqueInBackOfTransmissionBuffer(Packet * p)
+{
+// return 1 when succesfully enqueued, 0 when buffer is full
+
+   int r_value = 0;
+
+
+   if (transmissionBuffer_.length() >= bufferLevelMax_) {
+      drop(p);
+   } else {
+      transmissionBuffer_.enque(p);
+      r_value = 1;
+   }
+
+
+   return r_value;
+}
+
+
+
+//---------------------------
+// sendDown processes a SDU into PDUs for transmission to MAC-HS
+// if possible, waiting temporary packets are filled up.
+//---------------------------
+
+void UM::sendDown(Packet * p)
+{
+
+   // First check whether the SDU fits into the transmission buffer completely
+
+   int numPDUs =
+         (int) ceil((double) hdr_cmn::access(p)->size() /
+                    (double) payloadSize_);
+
+   if (numPDUs + transmissionBuffer_.length() >= bufferLevelMax_) {
+      Packet::free(p);
+      return;
+   }
+
+   int segment = 0;
+
+   // First check whether there is still a not-finished PDU available that can
+   // be used for concatenation.
+   handleTemporaryPacket(p);
+
+   if (hdr_rlc::access(p)->segment() == 0) {
+      // There was something that could be concatenated, and thus the first
+      // segment of the packet was already sent, so continue with the next.
+      segment++;
+   }
+
+   while (p != NULL) {
+      // Each loop the front of the SDU is removed and send in a PDU. This
+      // results in a smaller and smaller SDU, until at some point in time
+      // it is completely gone. In that case p equals to NULL and the
+      // complete SDU is segmented.
+
+      int concat_data = 0;
+      bool close_PDU = false;
+      int padding = 0;
+      bool force_length_indicator = false;
+      Packet     *c;
+
+      int p_size = hdr_cmn::access(p)->size();
+
+      close_PDU = p_size <= payloadSize_;
+      force_length_indicator = p_size < payloadSize_;
+
+      if (p_size <= (payloadSize_ - lengthIndicatorSize_)) {
+         // decide whether the remaining data is too big too keep
+         // in which case we send it on with padding
+         concat_data = payloadSize_ - p_size - 2 * lengthIndicatorSize_;
+         if (concat_data < min_concat_data_) {
+            concat_data = 0;
+            padding = payloadSize_ - p_size - lengthIndicatorSize_;
+         } else {
+            padding = 0;
+         }
+      }
+
+      if (close_PDU) {
+         // reuse packet p
+         c = p;
+         p = NULL;
+      } else {
+         // copy p's data into c and force concat_data and padding to 0
+         concat_data = 0;
+         padding = 0;
+         c = p->copy();
+      }
+
+
+      //initialise shortcuts to c's header info
+      hdr_cmn    *c_ch = HDR_CMN(c);
+      hdr_rlc    *c_llh = hdr_rlc::access(c);
+      hdr_cmn    *p_ch = NULL;
+      hdr_ip     *p_iph = NULL;
+
+      if (p != NULL) {
+         p_ch = HDR_CMN(p);
+         p_iph = hdr_ip::access(p);
+      }
+
+      c_llh->lptype() = c_ch->ptype();
+      c_llh->lerror_ = c_ch->error();
+      c_llh->lts_ = c_ch->timestamp();
+      c_llh->segment() = segment;
+      segment++;
+
+      if (close_PDU) {
+
+         if (SDU_size_ > 0) {
+            c_llh->lsize_ = SDU_size_;
+         } else {
+            c_llh->lsize_ = c_ch->size();
+         }
+
+         SDU_size_ = -1;
+
+      } else if (SDU_size_ < 0) {
+         assert(p != NULL);
+         SDU_size_ = hdr_cmn::access(p)->size();
+      }
+
+      c_llh->lltype() = RLC_DATA;
+      c_llh->seqno() = seqno_;
+      seqno_++;
+      c_llh->dst() = d_address_;
+      c_llh->src() = address_;
+      c_llh->lengthInd_ = 0;
+
+      if (close_PDU) {
+         // c_llh->eopno_ needs to be set to c_llh->seqno_. However, at this
+         // moment the seqno is not known yet. So, set it to EOPNO_TO_SEQNO
+         // and check when seqno is set whether eopno is EOPNO_TO_SEQNO. If this
+         // is the case eopno can be replaced by seqno.
+         c_llh->eopno_ = EOPNO_TO_SEQNO;
+      } else {
+         c_llh->eopno_ = EOPNO_NOT_EOP;
+      }
+
+      if (concat_data || padding || force_length_indicator) {
+         c_llh->lengthInd_++;
+      }
+
+      if (close_PDU) {
+         c_llh->payload_[PAYLOAD_FLD1] = c_ch->size();
+      } else {
+         if (force_length_indicator) {
+            c_llh->payload_[PAYLOAD_FLD1] = payloadSize_ - lengthIndicatorSize_;
+         } else {
+            c_llh->payload_[PAYLOAD_FLD1] = payloadSize_;
+         }
+      }
+      c_llh->payload_[PAYLOAD_FLD2] = 0;
+      c_llh->payload_[PAYLOAD_FLD3] = 0;
+
+      c_llh->padding_ = padding; //padding will always have the correct value here
+
+      // WTF? this is really ugly, bad things will happen here!
+      char       *mh = (char *) c->access(hdr_mac::offset_);
+      struct hdr_mac *c_dh = (struct hdr_mac *) mh;
+
+      c_ch->ptype() = PT_UM;
+      c_dh->macDA_ = macDA_;
+      c_dh->macSA_ = -1;
+      c_dh->hdr_type() = ETHERTYPE_RLC;
+      c_ch->timestamp() = Scheduler::instance().clock();
+
+      // Do we have space left over for concatenation?
+      if (close_PDU) {
+         if (concat_data) {
+            // Store the current packet and do not send it down.
+            // Because this is also the last part of the SDU we can
+            // stop this method.
+            c_llh->lengthInd_++;
+
+            StoreTemporaryPacket(c, concat_data);
+            break;              //exit while loop
+         }
+      } else {
+         // reduce the size of the SDU by an amount of the
+         // payload that will be sent in this PDU.
+         p_ch->size() = p_ch->size() - c_llh->payload_[PAYLOAD_FLD1];
+      }
+
+      assert(c_ch->error() == 0);
+
+
+      c_ch->size() = payloadSize_;
+
+
+      //----------
+      if (enquePacket(c) == 0) {
+      } else {
+      }
+
+   }
+
+
+}
+
+// This method is called when a PDU is created that is not full, and just stores
+// the PDU into a vector that will be inspected
+
+void UM::StoreTemporaryPacket(Packet * p, int concat_data)
+{
+
+   temporaryPacket_.p = p;
+   temporaryPacket_.concat_data = concat_data;
+   // We can't wait forever, because then we have a problem at the end of a
+   // burst of traffic: then the last PDU won't be send, causing timeouts and
+   // retransmissions. So, we do want to send the incomplete packet anyway
+   // at some point in time.
+   temporaryPacket_.tempPDUTimer.sched(tempPDUTimeOutTime_);
+}
+
+
+void UM::handleTemporaryPacket(Packet * p)
+{
+
+
+   if (p == NULL) {
+      return;
+   }
+   // Fill the temporary PDU with data from the new SDU, and delete that
+   // part of the SDU. Then store the temporary PDU in the Transmission
+   // and Retransmission Buffers and return the remaining part of the SDU.
+
+   // Concatenation (3GPP TS 25.301 5.3.2.2): If the contents of an RLC
+   // SDU cannot be carried by one RLC PDU, the first segment of the next
+   // RLC SDU may be put into the RLC PDU in concatenation with the last
+   // segment of the previous RLC SDU.
+
+   if (temporaryPacket_.p != NULL) {
+
+      if (hdr_cmn::access(p)->size() > payloadSize_) {
+
+         // TODO: check whether temporaryPacket exists
+
+         hdr_rlc::access(temporaryPacket_.p)->payload_[1] =
+               temporaryPacket_.concat_data;
+         // this variable was previously set in makePDU
+         SDU_size_ = hdr_cmn::access(p)->size();
+         hdr_cmn::access(p)->size() =
+               hdr_cmn::access(p)->size() - temporaryPacket_.concat_data;
+
+         // Set the segemnt to 0, in this way it is known that segmentation
+         // did occur.
+         hdr_rlc::access(p)->segment() = 0;
+
+      } else {
+
+         hdr_rlc::access(temporaryPacket_.p)->lengthInd_--;
+         hdr_rlc::access(temporaryPacket_.p)->padding_ =
+               temporaryPacket_.concat_data + lengthIndicatorSize_;
+      }
+      enquePacket(temporaryPacket_.p);
+
+      // Now the temporary PDU has been sent, delete the timer
+      // so that the timeout will not occur anymore.
+      temporaryPacket_.tempPDUTimer.cancel();
+      temporaryPacket_.p = NULL;
+   }
+}
+
+
+void UM::timeout(int tno, int flowID)
+{
+   vector < int >temp_vect;
+
+   double TTI_time_;
+   int TTI_PDUs_;
+
+   switch (tno) {
+     case RLC_TIMER_TEMP_PDU:
+
+        // Before we stored the temporary PDU in the
+        // vector, we set the number of Length Indicators
+        // and the number of bytes that could be
+        // concatenated. Because we are not concatenating,
+        // but padding we need one Length Indicator less,
+        // thus we have to pad more.
+        hdr_rlc::access(temporaryPacket_.p)->lengthInd_--;
+        hdr_rlc::access(temporaryPacket_.p)->padding_ =
+              temporaryPacket_.concat_data + lengthIndicatorSize_;
+        enquePacket(temporaryPacket_.p);
+
+        break;
+     case RLC_TIMER_TTI:
+        TTI_time_ = Scheduler::instance().clock();
+        TTI_PDUs_ = (int) (bandwidth_ * TTI_) / (payloadSize_ * 8);
+        tti_timer_.resched(TTI_);
+        for (int i = 0; i < TTI_PDUs_; i++) {
+           //send_packet_down
+           Packet     *p = transmissionBuffer_.deque();
+
+           if (p != NULL) {
+              downtarget_->recv(p);
+           }
+        }
+        break;
+     default:
+        break;
+   }
+
+}
+
+void UM::completePDU(Packet * p)
+{
+
+
+   hdr_rlc    *llh = hdr_rlc::access(p);
+
+   // If the packet is transmitted for the first time, set the sequence number
+   // and possibly the eop number.
+   if (llh->seqno() == -1) {
+      llh->seqno() = seqno_;
+      seqno_++;
+      if (llh->eopno() == EOPNO_TO_SEQNO) {
+         llh->eopno() = llh->seqno();
+      }
+   }
+   return;
+}
+
+void UM::makeSDU(Packet * p)
+{
+   hdr_cmn    *ch;
+   hdr_rlc    *llh;
+
+   assert(p);
+   ch = HDR_CMN(p);
+   llh = hdr_rlc::access(p);
+
+   ch->ptype() = llh->lptype();
+   ch->error() = llh->lerror();
+   ch->timestamp() = llh->lts();
+   ch->size() = llh->lsize();
+
+   uptarget_ ? sendUp(p) : Packet::free(p);
+}
+
+int UM::buff_size()
+{
+   return(transmissionBuffer_.size());
+}
+
+void UM::CSwitch(double bandwidth, double TTI)
+{
+	   bandwidth_ = bandwidth;
+	      TTI_ = TTI;
+}
+
diff -urN ns-2.30-orig/umts/um.h ns-2.30-eu112/umts/um.h
--- ns-2.30-orig/umts/um.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/um.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: um.h,v 1.1 2005/04/27 14:30:10 simon Exp $
+ */
+
+// This file both defines the RLC header and UM.
+
+#ifndef ns_um_h
+#define ns_um_h
+
+#include "ll.h"
+#include "rlc.h"
+#include "umts-queue.h"
+#include "umts-timers.h"
+#include "umts-headers.h"
+#include "queue.h"
+#include "agent.h"
+#include "packet.h"
+#include "timer-handler.h"
+#include <vector>
+
+
+#define EOPNO_NOT_EOP -1
+#define EOPNO_TO_SEQNO -2
+
+#define PAYLOAD_FLD1 0
+#define PAYLOAD_FLD2 1
+#define PAYLOAD_FLD3 2
+
+
+class temporaryPacket {
+public:
+   temporaryPacket(RLC * rlc):tempPDUTimer(rlc, RLC_TIMER_TEMP_PDU) {
+   } Packet   *p;
+   int         concat_data;
+   UmtsTimer   tempPDUTimer;
+};
+
+
+class UM:   public RLC {
+public:
+   UM();
+   virtual void recv(Packet *, Handler *);
+   int         command(int, const char *const *);
+   void        timeout(int tno, int flowID = -1);
+   int         buff_size();
+   void        CSwitch(double, double);
+
+protected:
+   int         enquePacket(Packet * p);
+   int         enqueInBackOfTransmissionBuffer(Packet * p);
+   void        sendDown(Packet * p);
+   void        StoreTemporaryPacket(Packet * p, int concat_data);
+   void        handleTemporaryPacket(Packet * p);
+   void        completePDU(Packet * p);
+   void        makeSDU(Packet * p);
+
+   int         lengthIndicatorSize_;
+   // The size of the Length indicator + the
+   // extention bit. The size is in bytes. The
+   // size is 1 or 2 bytes depending on the size
+   // of the PDUs.
+
+   // parameters of the object, set through TCL
+
+   int         win_;
+   // defines the RLC Window Size, which is the amount of packets that can be
+   // sent after the last acknowledged packet.
+
+   int         bufferLevelMax_;
+   // The maximum number of PDUs for each flow-id and
+   // priority pair in the Transmission Buffer.
+
+   double      tempPDUTimeOutTime_;
+   // When a PDU is constructed that has some
+   // space left, the PDU is stored in the vector
+   // temporaryPackets_. A timeout will be set
+   // to ensure that when no further SDU arrives
+   // with the same flow-id and priority, the
+   // not-full PDU will be sent and will not
+   // wait indefinitely.
+
+   temporaryPacket temporaryPacket_;
+   // In this vector Temporary PDUs are stored. These are PDUs that a not
+   // completely full, and they can be possibly concatenated with a part of
+   // a new SDU. However, this concatenation should be done quick enough,
+   // otherwise timeouts and unnesessary delays may occur. So, a timer will
+   // be set, when the concatenation can be done before the timer times out,
+   // the PDU will be concatenated with a part of a new SDU. When the timer
+   // times out, the Temporary Packet is padded and sent without concatenation.
+
+   double      overhead_;       // Time that is needed to contruct SDUs
+
+   int         payloadSize_;    // user data per DATA PDU
+   double      TTI_;
+
+   int         length_indicator_;
+   int         min_concat_data_;
+
+   int         address_;        // address of this RLC Entity
+
+   umtsQueue   transmissionBuffer_;
+   // For our Transmission Buffer we use a vector of rlcQueue, for each
+   // flow-id and priority-pair one queue exists.
+
+   int         nextExpectedSDU_;
+   int         nextExpectedSeqno_;
+   int         nextExpectedSegment_;
+   int         errorInSDU_;
+
+   int         seqno_;
+
+   int         send_status_;
+   int         SDU_size_;       // stores the original size of the SDU when a part already
+   // was concatenated
+
+   int         maxseq_;         // highest seqno transmitted so far
+   int         highest_ack_;    // highest ack recieved by sender
+   int         maxseen_;        // max PDU (seqno)number seen by receiver
+//   int seen_[MWS];   // array of PDUs seen by reciever
+   int         next_;           // next PDU expected by reciever
+
+   int         d_address_;      // destination address of this RLC Entity
+   int         macDA_;          // mac destination address for packets created by this RLC
+   // Entity
+
+   umtsQueue   sduB_;
+
+   UmtsTimer   tti_timer_;
+
+};
+
+
+#endif
diff -urN ns-2.30-orig/umts/umts-headers.h ns-2.30-eu112/umts/umts-headers.h
--- ns-2.30-orig/umts/umts-headers.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umts-headers.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: umts-headers.h,v 1.1 2004/01/21 15:55:12 wtdavid Exp $
+ */
+
+#ifndef ns_umts_headers_h
+#define ns_umts_headers_h
+
+
+#define ETHERTYPE_RLC 0x0900 // Type of Payload in MAC frame
+
+enum RLCFrameType {
+   RLC_DATA = 0x0000,           /* Data RLC PDU */
+   RLC_ACK = 0x0001,            /* Positive ACK PDU (like Tahoe) */
+   RLC_BACK = 0x0010,           /* Bitmap ACK PDU */
+   RLC_PB_ACK = 0x0100,
+   RLC_PB_BACK = 0x1000,
+};
+
+
+struct hdr_rlc {
+   packet_t    lptype_;         // SDU type
+   int         lerror_;         // error flag of SDU
+   double      lts_;            // ts value of SDU
+   int         lsize_;          // payload SDU size
+
+   RLCFrameType lltype_;        // RLC frame type
+   int         seqno_;          // PDU sequence number
+   int         a_seqno_;        // PDU sequence number
+   int         eopno_;          // end of SDU seqno
+   int         segment_;        // the segment number of the PDU, starts with 0 for the first
+   // PDU of a SDU.
+   bool        poll_;           // poll flag
+
+   int         payload_[3];
+   int         lengthInd_;
+   int         padding_;
+
+   int         FSN_;
+   int         length_;
+   int        *bitmap_;
+
+   nsaddr_t    src_;
+   nsaddr_t    dst_;
+
+   static int  offset_;
+   inline int &offset() {
+      return offset_;
+   } static hdr_rlc *access(const Packet * p) {
+      return (hdr_rlc *) p->access(offset_);
+   }
+
+   packet_t & lptype() {
+      return (lptype_);
+   }
+   int        &lerror() {
+      return lerror_;
+   }
+   double     &lts() {
+      return (lts_);
+   }
+   int        &lsize() {
+      return lsize_;
+   }
+
+   RLCFrameType & lltype() {
+      return lltype_;
+   }
+   int        &seqno() {
+      return seqno_;
+   }
+   int        &a_seqno() {
+      return a_seqno_;
+   }
+   int        &eopno() {
+      return eopno_;
+   }
+   int        &segment() {
+      return segment_;
+   }
+   bool       &poll() {
+      return poll_;
+   }
+
+   int        &FSN() {
+      return FSN_;
+   }
+   int        &length() {
+      return length_;
+   }
+   int        &bitmap(int i) {
+      return bitmap_[i];
+   }
+
+   int        &lengthInd() {
+      return lengthInd_;
+   }
+   int        &padding() {
+      return padding_;
+   }
+   int        &payload(int i) {
+      return payload_[i];
+   }
+
+   nsaddr_t & src() {
+      return (src_);
+   }
+   nsaddr_t & dst() {
+      return (dst_);
+   }
+};
+
+#endif
diff -urN ns-2.30-orig/umts/umts-queue.cc ns-2.30-eu112/umts/umts-queue.cc
--- ns-2.30-orig/umts/umts-queue.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umts-queue.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: umts-queue.cc,v 1.22 2004/02/20 11:31:09 simon Exp $
+ */
+
+#include "umts-queue.h"
+#include <assert.h>
+
+umtsQueue::umtsQueue():TclObject()
+{
+   lastServedTime_ = 0.0;
+   tx_seq_nr_ = 0;
+   len_ = 0;
+}
+
+// Insert the packet in back of the queue
+void umtsQueue::enque(Packet * p)
+{
+   if (q_.empty()) {
+      lastServedTime_ = Scheduler::instance().clock();
+   }
+   q_.push_back(p);
+   len_++;
+}
+
+// Insert the packet in front of the queue
+void umtsQueue::enqueUniqueFront(Packet * p)
+{
+   int seqno = hdr_rlc::access(p)->seqno();
+
+   //lastServedTime_ = Scheduler::instance().clock();
+   for (unsigned int i = 0; i < q_.size(); i++) {
+      int temp_seqno = hdr_rlc::access(q_.at(i))->seqno();
+
+      if (temp_seqno == seqno) {
+         return;
+      }
+   }
+   q_.insert(q_.begin(), p);
+   len_++;
+}
+
+// Insert the packet in front of the queue
+void umtsQueue::printQueue()
+{
+   if (q_.size() > 0) {
+      for (unsigned int i = 0; i < q_.size(); i++) {
+         printf ("%d ", hdr_rlc::access(q_.at(i))->seqno() );
+      }
+      printf ("\n");
+   }
+
+}
+
+// Insert the packet in sequence in the queue. If all the packets are inserted by
+// this method, the queue is ordered.
+void umtsQueue::orderedEnque(Packet * p)
+{
+
+   if (q_.empty()) {
+      lastServedTime_ = Scheduler::instance().clock();
+
+   }
+
+   int seqno = hdr_rlc::access(p)->seqno();
+
+   for (unsigned int i = 0; i < q_.size(); i++) {
+      if ((hdr_rlc::access(q_.at(i)))->seqno() > seqno) {
+         q_.insert(q_.begin() + i, p);
+         len_++;
+         return;
+      }
+   }
+   q_.push_back(p);
+   len_++;
+}
+
+// Return the first packet from the queue, and remove the packet from the queue
+Packet     *umtsQueue::deque()
+{
+   lastServedTime_ = Scheduler::instance().clock();
+
+   if (q_.empty()) {
+      return NULL;
+   }
+   Packet     *temp = q_.front();
+
+   q_.erase(q_.begin());
+   len_--;
+   return temp;
+}
+
+// Return the last packet from the queue, and remove the packet from the queue
+Packet     *umtsQueue::dequeTail()
+{
+   if (q_.size() == 1) {
+      lastServedTime_ = Scheduler::instance().clock();
+
+   }
+   Packet     *temp = q_.back();
+
+   q_.pop_back();
+   len_--;
+   return temp;
+}
+
+// Return a pointer to a copy of the first packet from the queue
+Packet     *umtsQueue::dequeCopy()
+{
+   if (q_.empty()) {
+      return NULL;
+   }
+   return q_.front()->copy();
+}
+
+// Return a pointer to a copy of the last packet from the queue
+Packet     *umtsQueue::dequeTailCopy()
+{
+   if (q_.empty()) {
+      return NULL;
+   }
+   return q_.back()->copy();
+}
+
+// Return the packet with a certain seqno from the queue, and remove the packet
+// from the queue
+Packet     *umtsQueue::deque(int seqno)
+{
+   for (unsigned int i = 0; i < q_.size(); i++) {
+      if ((hdr_rlc::access(q_.at(i)))->seqno() == seqno) {
+         Packet     *temp = q_.at(i);
+
+         q_.erase(q_.begin() + i);
+         len_--;
+         return temp;
+      }
+   }
+   return NULL;
+}
+
+// Return a pointer to a copy of the packet with a certain seqno from the queue
+Packet     *umtsQueue::dequeCopy(int seqno)
+{
+   for (unsigned int i = 0; i < q_.size(); i++) {
+      if ((hdr_rlc::access(q_.at(i)))->seqno() == seqno) {
+         return q_.at(i)->copy();
+      }
+   }
+   return NULL;
+}
+
+// Returns the first packet with a seqno >= 0
+Packet     *umtsQueue::dequeFirstSendable()
+{
+
+   unsigned int pos = 0;
+
+   while (pos < q_.size() && ((hdr_rlc::access(q_.at(pos)))->seqno() < 0)) {
+      pos++;
+   }
+   // pos is now the first packet with seqno >= 0, unless pos == q_.size
+
+   Packet     *temp = NULL;
+
+   if (pos < q_.size()) {
+      temp = q_.at(pos);
+      q_.erase(q_.begin() + pos);
+      len_--;
+   }
+
+   return temp;
+}
+
+// Removes all packets with a seqno less to a certain seqno from the
+// queue and free the packets belonging to the queued pointers.
+void umtsQueue::dropTill(int seqno)
+{
+   for (unsigned int i = 0; i < q_.size(); /* do nothing */ ) {
+      // Do not drop sequence numbers lower than 0, because these have not been
+      // set yet.
+      if (((hdr_rlc::access(q_.at(i)))->seqno() < seqno)
+          && ((hdr_rlc::access(q_.at(i)))->seqno() >= 0)) {
+         assert(q_.at(i) != NULL);
+         Packet::free(q_.at(i));
+
+         q_.erase(q_.begin() + i);
+         len_--;
+      } else {
+         i++;
+      }
+   }
+}
+
+void umtsQueue::updateLastServedTime()
+{
+   lastServedTime_ = Scheduler::instance().clock();
+
+}
+
+// Returns the total size of all the packets in the queue, in bytes
+int umtsQueue::size()
+{
+   int size = 0;
+
+   for (unsigned int i = 0; i < q_.size(); i++) {
+      size = size + hdr_cmn::access(q_.at(i))->size();
+   }
+   return size;
+}
+
+//returns packetsize of the first packet in the queue or at pos
+// returns -1 when nothing in the queue
+int umtsQueue::getPacketSize() {
+   if (q_.empty()) {
+      return -1;
+   } else {
+      return hdr_cmn::access(q_.front())->size();
+   }
+}
+
+// Returns the size of the packet at a certain position in the queue, in bytes
+int umtsQueue::size(int position)
+{
+   if (q_.size() < (unsigned) position) {
+      return 0;
+   }
+   return hdr_cmn::access(q_.at(position - 1))->size();
+}
+
+// Returns the total size of all the packets in the queue, in bits
+int umtsQueue::sizeInBits()
+{
+   return size() * 8;
+}
+
+// Returns the size of the packet at a certain position in the queue, in bits
+int umtsQueue::sizeInBits(int position)
+{
+   return size(position) * 8;
+}
+
+// TODO: change code in am so this method can be deleted
+// Reduces the size of the first packet with a certain amount of bytes. This is
+// only done when the packet is large enough
+int umtsQueue::red_size(int bytes)
+{
+   int size = (hdr_cmn::access(q_.at(0)))->size();
+
+   if (q_.empty() || size <= bytes) {
+      return -1;
+   }
+   (hdr_cmn::access(q_.at(0)))->size() = size - bytes;
+   return size;
+}
+
+// Returns the number of packets in the queue
+int umtsQueue::length()
+{
+   return q_.size();
+}
+
diff -urN ns-2.30-orig/umts/umts-queue.h ns-2.30-eu112/umts/umts-queue.h
--- ns-2.30-orig/umts/umts-queue.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umts-queue.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: umts-queue.h,v 1.11 2004/02/06 16:34:02 simon Exp $
+ */
+
+#ifndef ns_umtsQueue_h
+#define ns_umtsQueue_h
+
+
+#include "packet.h"
+#include "umts-headers.h"
+#include <vector>
+
+
+class umtsQueue:public TclObject {
+public:
+   umtsQueue();
+
+   void        enque(Packet * p);
+   void        enqueUniqueFront(Packet * p);
+   void        orderedEnque(Packet * p);
+   Packet     *deque();
+   Packet     *dequeTail();
+   Packet     *dequeCopy();
+   Packet     *dequeTailCopy();
+   Packet     *deque(int seqno);
+   Packet     *dequeCopy(int seqno);
+   Packet     *dequeFirstSendable();
+   void        updateLastServedTime();
+   int         getPacketSize();
+   void        dropTill(int seqno);
+   void        printQueue();
+   int         size();
+   int         size(int position);
+   int         sizeInBits();
+   int         sizeInBits(int position);
+   int         length();
+   int         red_size(int bytes);
+
+   // lastServedTime_ is set to the current simulation time, when the first
+   // element is changed. This enables round-robin schedulers to determine
+   // which queue to handle.
+   double      lastServedTime_;
+
+   // for debugging purposes only...
+   int         len_;
+
+   // TODO: change hsdpalink in such a way that this variable isn't needed here
+   // anymore.
+   int         tx_seq_nr_;      // last TSN
+
+private:
+               vector < Packet * >q_;
+
+};
+
+#endif
diff -urN ns-2.30-orig/umts/umts-timers.cc ns-2.30-eu112/umts/umts-timers.cc
--- ns-2.30-orig/umts/umts-timers.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umts-timers.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: umts-timers.cc,v 1.18 2004/01/20 13:29:24 simon Exp $
+ */
+
+#include "umts-timers.h"
+
+UmtsTimer::UmtsTimer(RLC * rlc, int timeoutNumber, int flowID):TimerHandler()
+{
+
+   if (rlc != NULL) {
+      rlc_ = rlc;
+      timeoutNumber_ = timeoutNumber;
+   } else {
+   }
+}
+
+void UmtsTimer::expire(Event *)
+{
+   rlc_->timeout(timeoutNumber_);
+}
+
+double UmtsTimer::timeOfExpiry()
+{
+   return event_.time_;
+}
+
+
+char       *UmtsTimer::getName()
+{
+   switch (timeoutNumber_) {
+     case RLC_TIMER_POLL:
+        return "RLC_TIMER_POLL";
+        break;
+     case RLC_TIMER_RTX:
+        return "RLC_TIMER_RTX";
+        break;
+     case RLC_TIMER_DELSND:
+        return "RLC_TIMER_DELSND";
+        break;
+     case RLC_TIMER_STPROB:
+        return "RLC_TIMER_STPROB";
+        break;
+     case RLC_TIMER_TTI:
+        return "RLC_TIMER_TTI";
+        break;
+     case RLC_TIMER_TEMP_PDU:
+        return "RLC_TIMER_TEMP_PDU";
+        break;
+     case RLC_TIMER_CREDIT:
+        return "RLC_TIMER_CREDIT";
+        break;
+     case RLC_TIMER_STATUS:
+        return "RLC_TIMER_STATUS";
+        break;
+     default:
+        return "UNKNOWN";
+        break;
+   }
+}
+
+HsdpaMacTimer::HsdpaMacTimer(VirtualUmtsMac * mac, int timeoutNumber,
+                             int flowID):TimerHandler()
+{
+   mac_ = mac;
+   timeoutNumber_ = timeoutNumber;
+   flowID_ = flowID;
+}
+
+void HsdpaMacTimer::expire(Event *)
+{
+   mac_->timeout(timeoutNumber_);
+}
+
+double HsdpaMacTimer::timeOfExpiry()
+{
+   return event_.time_;
+}
+
+char       *HsdpaMacTimer::getName()
+{
+   switch (timeoutNumber_) {
+     case MACHS_TIMER_FRAME:
+        return "MACHS_TIMER_FRAME";
+        break;
+     case MACHS_TIMER_CREDALLOC:
+        return "MACHS_TIMER_CREDALLOC";
+        break;
+     case MACHS_TIMER_SCHEDULE:
+        return "MACHS_TIMER_SCHEDULE";
+        break;
+     case MACHS_TIMER_REORDER_STALL:
+        return "MACHS_TIMER_REOR";
+        break;
+     case MACHS_TIMER_PROCESS_CLEAR:
+        return "MACHS_TIMER_PROCESS_CLEAR";
+        break;
+     default:
+        return "UNKNOWN HSDPAMAC TIMER";
+        break;
+   }
+}
+
+//
+void UmtsTimer::cancel()
+{
+   if (status_ != TIMER_PENDING) {
+      return;
+   } else {
+      ((TimerHandler *) this)->cancel();
+   }
+}
+
+void UmtsTimer::sched(double delay)
+{
+   if (delay >= 0) {
+      ((TimerHandler *) this)->sched(delay);
+   } else {
+      abort();
+   }
+}
+
+void UmtsTimer::resched(double delay)
+{
+   if (delay >= 0) {
+      ((TimerHandler *) this)->resched(delay);
+   } else {
+      abort();
+   }
+}
+
+
+void HsdpaMacTimer::cancel()
+{
+
+   if (status_ != TIMER_PENDING) {
+      return;
+   } else {
+      ((TimerHandler *) this)->cancel();
+   }
+}
+
+void HsdpaMacTimer::sched(double delay)
+{
+   if (delay >= 0) {
+      ((TimerHandler *) this)->sched(delay);
+   } else {
+      abort();
+   }
+}
+
+void HsdpaMacTimer::resched(double delay)
+{
+   if (delay >= 0) {
+      ((TimerHandler *) this)->resched(delay);
+   } else {
+      abort();
+   }
+}
diff -urN ns-2.30-orig/umts/umts-timers.h ns-2.30-eu112/umts/umts-timers.h
--- ns-2.30-orig/umts/umts-timers.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umts-timers.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id$
+ */
+
+
+#ifndef ns_umts_timers_h
+#define ns_umts_timers_h
+
+#include "virtual_umtsmac.h"
+#include "rlc.h"
+#include "timer-handler.h"
+
+
+#define RLC_TIMER_POLL		0
+#define RLC_TIMER_RTX		1
+#define RLC_TIMER_DELSND	2
+#define RLC_TIMER_STPROB	3
+#define RLC_TIMER_TTI		4
+#define RLC_TIMER_TEMP_PDU	5 // Timeout for Temporary PDUs, in order
+                             // not to get a deadlock when the last
+                             // PDU is not followed by another PDU.
+#define RLC_TIMER_CREDIT	6 // Timeout for sending a PDU in the
+                             // Transmission Buffer.
+#define RLC_TIMER_STATUS	7 // Timeout for sending Status Information
+                             // in a separate PDU.
+
+
+#define MACHS_TIMER_FRAME      10
+#define MACHS_TIMER_CREDALLOC  11
+#define MACHS_TIMER_SCHEDULE   12
+#define MACHS_TIMER_REORDER_STALL 13
+#define MACHS_TIMER_PROCESS_CLEAR 14
+
+class UmtsTimer:public TimerHandler {
+public:
+   UmtsTimer(RLC * rlc, int timeoutNumber, int flowID = -1);
+   double      timeOfExpiry();
+   char       *getName();
+   void        cancel();        // overloaded from TimerHandler
+   void        sched(double delay); // overloaded from TimerHandler
+   void        resched(double delay);  // overloaded from TimerHandler
+protected:
+   virtual void expire(Event * e);
+   RLC        *rlc_;
+   int         timeoutNumber_;
+};
+
+
+class HsdpaMacTimer:public TimerHandler {
+public:
+   HsdpaMacTimer(VirtualUmtsMac * mac, int timeoutNumber, int flowID = -1);
+   double      timeOfExpiry();
+   char       *getName();
+   void        cancel();        // overloaded from TimerHandler
+   void        sched(double delay); // overloaded from TimerHandler
+   void        resched(double delay);  // overloaded from TimerHandler
+protected:
+   virtual void expire(Event * e);
+   VirtualUmtsMac *mac_;
+   int         timeoutNumber_;
+   int         flowID_;
+};
+
+
+#endif //ns_umts_timers_h
diff -urN ns-2.30-orig/umts/umtslink.cc ns-2.30-eu112/umts/umtslink.cc
--- ns-2.30-orig/umts/umtslink.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umtslink.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: umtslink.cc,v 1.11 2004/01/20 13:29:24 simon Exp $
+ */
+
+#include "umtslink.h"
+#include "random.h"
+
+
+
+/*
+ * UmtsMac
+ */
+
+static class UmtsMacClass:public TclClass {
+public:
+   UmtsMacClass():TclClass("Mac/Umts") {
+   } TclObject *create(int, const char *const *) {
+      return (new UmtsMac);
+   }
+}
+
+umts_class_mac;
+
+
+void PhyFrame_Timer::expire(Event *)
+{
+   a_->timeout(0);
+}
+
+
+UmtsMac::UmtsMac():VirtualUmtsMac(), avg_delay_(0), frame_timer_(this)
+{
+   bind_time("TTI_", &TTI_);
+   bind_time("shared_delay_", &shared_delay_);
+   fflush(stdout);
+}
+
+int UmtsMac::command(int argc, const char *const *argv)
+{
+   if (argc == 2) {
+      Tcl & tcl = Tcl::instance();
+      if (strcmp(argv[1], "set_access_delay") == 0) {
+         avg_delay_ = shared_delay_;
+         return TCL_OK;
+      } else if (strcmp(argv[1], "TTI") == 0) {
+         tcl.resultf("%f", TTI_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "BW") == 0) {
+         tcl.resultf("%f", bandwidth_);
+         return TCL_OK;
+      } else if (strcmp(argv[1], "start_TTI") == 0) {
+         frame_timer_.sched(TTI_);
+         return TCL_OK;
+      }
+   } else if (argc == 3) {
+      if (strcmp(argv[1], "SA") == 0) {
+         index_ = atoi(argv[2]);
+         return TCL_OK;
+      }
+   }
+   return Mac::command(argc, argv);
+}
+
+void UmtsMac::timeout(int tno)
+{
+   if (tno == 0) {
+      if (q_.length() == 0) {
+         frame_timer_.resched(TTI_);
+         return;
+      }
+
+      double delay = Random::uniform(avg_delay_);
+      double txt = TTI_;
+
+      if (avg_delay_ != 0) {
+         txt = txt + delay;
+      }
+
+      double data = 0;
+      double bits_to_send = bandwidth_ * TTI_;
+      Packet     *p = q_.dequeCopy();
+
+      while ((data + (hdr_cmn::access(p)->size() * 8))
+             <= bits_to_send) {
+         Packet::free(p);
+         p = q_.deque();
+         data = data + (hdr_cmn::access(p)->size() * 8);
+         // For convenience, we encode the transmit time
+         // in the Mac header
+         HDR_MAC(p)->txtime() = txt;
+         downtarget_->recv(p, this);
+         if (q_.length()) {
+            p = q_.dequeCopy();
+         } else {
+            frame_timer_.resched(TTI_);
+            return;
+         }
+      }
+      Packet::free(p);
+      frame_timer_.resched(TTI_);
+      return;
+   }
+}
+
+void UmtsMac::sendUp(Packet * p)
+{
+   hdr_mac    *mh = HDR_MAC(p);
+   int dst = this->hdr_dst((char *) mh);  // mac destination address
+
+//   hdr_cmn* ch = hdr_cmn::access(p);
+//   hdr_rlc* llh = hdr_rlc::access(p);
+//   hdr_ip* iph = hdr_ip::access(p);
+
+   if (dst == index_) {
+      // First bit of packet has arrived-- wait for
+      // (txtime + delay_) before sending up
+      Scheduler::instance().schedule(uptarget_, p, delay_ + mh->txtime());
+   } else {
+      Packet::free(p);
+   }
+}
+
+
+
+void UmtsMac::sendDown(Packet * p)
+{
+   double bPtti_ = bandwidth_ * TTI_;
+
+   if ((q_.size() + hdr_cmn::access(p)->size() * 8) > (bPtti_ * 2)) {
+      drop(p);
+   } else {
+      q_.enque(p);
+   }
+
+}
+
+
+/*
+ *  UmtsPhy
+ */
+
+static class UmtsPhyClass:public TclClass {
+public:
+   UmtsPhyClass():TclClass("Phy/Umts") {
+   } TclObject *create(int, const char *const *) {
+      return (new UmtsPhy);
+   }
+}
+
+class_UmtsPhy;
+
+void UmtsPhy::sendDown(Packet * p)
+{
+   if (channel_) {
+      channel_->recv(p, this);
+   } else {
+      Packet::free(p);
+   }
+}
+
+// Note that this doesn't do that much right now.  If you want to incorporate
+// an error model, you could insert a "propagation" object like in the
+// wireless case.
+int UmtsPhy::sendUp(Packet * /* pkt */ )
+{
+   return TRUE;
+}
+
+int UmtsPhy::command(int argc, const char *const *argv)
+{
+   return Phy::command(argc, argv);
+}
diff -urN ns-2.30-orig/umts/umtslink.h ns-2.30-eu112/umts/umtslink.h
--- ns-2.30-orig/umts/umtslink.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umtslink.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: umtslink.h,v 1.7 2004/01/20 13:29:24 simon Exp $
+ */
+
+#ifndef ns_umts_link_h
+#define ns_umts_link_h
+
+#include "phy.h"
+#include "virtual_umtsmac.h"
+#include "rlc.h"
+#include "um.h"
+#include "umts-queue.h"
+
+////////////////////////////MAC////////////////////////////
+
+class UmtsMac;
+
+class PhyFrame_Timer:public TimerHandler {
+public:
+   PhyFrame_Timer(UmtsMac * a):TimerHandler() {
+      a_ = a;
+} protected:
+   virtual void expire(Event * e);
+   UmtsMac    *a_;
+};
+
+
+class UmtsMac:public VirtualUmtsMac {
+public:
+   UmtsMac();
+   virtual void timeout(int tno);
+   void        sendUp(Packet * p);
+   void        sendDown(Packet * p);
+
+protected:
+   int         command(int argc, const char *const *argv);
+   double      avg_delay_;
+   double      shared_delay_;
+   double      TTI_;
+   umtsQueue   q_;
+   PhyFrame_Timer frame_timer_;
+};
+
+////////////////////////////PHY////////////////////////////
+
+class UmtsPhy:public Phy {
+public:
+   UmtsPhy() {
+   } void      sendDown(Packet * p);
+   int         sendUp(Packet * p);
+
+ protected:
+   int         command(int argc, const char *const *argv);
+};
+
+
+#endif
diff -urN ns-2.30-orig/umts/umtstrace.cc ns-2.30-eu112/umts/umtstrace.cc
--- ns-2.30-orig/umts/umtstrace.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umtstrace.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: umtstrace.cc,v 1.1 2005/04/27 14:30:10 simon Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "packet.h"
+#include "ip.h"
+#include "tcp.h"
+#include "rtp.h"
+#include "srm.h"
+#include "flags.h"
+#include "address.h"
+#include "trace.h"
+#include "tfrc.h"
+#include "rap/rap.h"
+#include "um.h"
+#include "umtstrace.h"
+
+
+class UMTSTraceClass:public TclClass {
+public:
+   UMTSTraceClass():TclClass("Trace/UMTS") {
+   } TclObject *create(int argc, const char *const *argv) {
+      if (argc >= 5) {
+         return (new UMTSTrace(*argv[4]));
+      }
+      return 0;
+   }
+}
+
+umts_trace_class;
+
+char       *srm_names__[] = {
+   SRM_NAMES
+};
+
+void UMTSTrace::format(int tt, int s, int d, Packet * p)
+{
+   if (s == -1) {
+      s = hdr_rlc::access(p)->src();
+   }
+   if (d == -1) {
+      d = hdr_rlc::access(p)->dst();
+   }
+   hdr_cmn    *th = hdr_cmn::access(p);
+   hdr_ip     *iph = hdr_ip::access(p);
+   hdr_tcp    *tcph = hdr_tcp::access(p);
+   hdr_srm    *sh = hdr_srm::access(p);
+   hdr_rlc    *rlch = hdr_rlc::access(p);
+
+   const char *sname = "null";
+
+   packet_t t = th->ptype();
+   const char *name = packet_info.name(t);
+
+   /* SRM-specific */
+   if (strcmp(name, "SRM") == 0 || strcmp(name, "cbr") == 0
+       || strcmp(name, "udp") == 0) {
+      if (sh->type() < 5 && sh->type() > 0) {
+         sname = srm_names__[sh->type()];
+      }
+   }
+
+   if (name == 0) {
+      abort();
+   }
+
+   int seqno = get_seqno(p);
+
+   /* 
+    * When new flags are added, make sure to change NUMFLAGS
+    * in trace.h
+    */
+   char flags[NUMFLAGS + 1];
+
+   for (int i = 0; i < NUMFLAGS; i++) {
+      flags[i] = '-';
+   }
+   flags[NUMFLAGS] = 0;
+
+   hdr_flags  *hf = hdr_flags::access(p);
+
+   flags[0] = hf->ecn_ ? 'C' : '-'; // Ecn Echo
+   flags[1] = hf->pri_ ? 'P' : '-';
+   flags[2] = '-';
+   flags[3] = hf->cong_action_ ? 'A' : '-';  // Congestion Action
+   flags[4] = hf->ecn_to_echo_ ? 'E' : '-';  // Congestion Experienced
+   flags[5] = hf->fs_ ? 'F' : '-';  // Fast start: see tcp-fs and tcp-int
+   flags[6] = hf->ecn_capable_ ? 'N' : '-';
+
+#ifdef notdef
+   flags[1] = (iph->flags() & PF_PRI) ? 'P' : '-';
+   flags[2] = (iph->flags() & PF_USR1) ? '1' : '-';
+   flags[3] = (iph->flags() & PF_USR2) ? '2' : '-';
+   flags[5] = 0;
+#endif
+   char       *src_nodeaddr = Address::instance().print_nodeaddr(iph->saddr());
+   char       *src_portaddr = Address::instance().print_portaddr(iph->sport());
+   char       *dst_nodeaddr = Address::instance().print_nodeaddr(iph->daddr());
+   char       *dst_portaddr = Address::instance().print_portaddr(iph->dport());
+
+   if (t == PT_UM || t == PT_AMDA || t == PT_AMPA || t == PT_AMBA
+       || t == PT_AMPBPA || t == PT_AMPBBA || t == PT_AMDA_H1 || t == PT_AMDA_H2 || t == PT_AMDA_H3) {
+      sprintf(pt_->buffer(),
+              "%c " TIME_FORMAT " %d %d %s %d %s %d %s.%s %s.%s %d %d %d", tt,
+              pt_->round(Scheduler::instance().clock()), s, d, name, th->size(),
+              flags, iph->flowid() /* was p->class_ */ ,
+              // iph->src() >> (Address::instance().NodeShift_[1]), 
+              // iph->src() & (Address::instance().PortMask_), 
+              // iph->dst() >> (Address::instance().NodeShift_[1]), 
+              // iph->dst() & (Address::instance().PortMask_),
+              src_nodeaddr, src_portaddr, dst_nodeaddr, dst_portaddr, seqno, th->uid(),   /* was p->uid_ */
+              rlch->seqno());
+
+   } else {
+
+      if (!show_tcphdr_) {
+         sprintf(pt_->buffer(),
+                 "%c " TIME_FORMAT " %d %d %s %d %s %d %s.%s %s.%s %d %d", tt,
+                 pt_->round(Scheduler::instance().clock()), s, d, name,
+                 th->size(), flags, iph->flowid() /* was p->class_ */ ,
+                 // iph->src() >> (Address::instance().NodeShift_[1]), 
+                 // iph->src() & (Address::instance().PortMask_), 
+                 // iph->dst() >> (Address::instance().NodeShift_[1]), 
+                 // iph->dst() & (Address::instance().PortMask_),
+                 src_nodeaddr, src_portaddr, dst_nodeaddr, dst_portaddr, seqno, th->uid());  /* was p->uid_ */
+      } else {
+         sprintf(pt_->buffer(), "%c " TIME_FORMAT " %d %d %s %d %s %d %s.%s %s.%s %d %d %d 0x%x %d %d", tt, pt_->round(Scheduler::instance().clock()), s, d, name, th->size(), flags, iph->flowid(),  /* was p->class_ */
+                 // iph->src() >> (Address::instance().NodeShift_[1]), 
+                 // iph->src() & (Address::instance().PortMask_), 
+                 // iph->dst() >> (Address::instance().NodeShift_[1]), 
+                 // iph->dst() & (Address::instance().PortMask_),
+                 src_nodeaddr, src_portaddr, dst_nodeaddr, dst_portaddr, seqno, th->uid(),   /* was p->uid_ */
+                 tcph->ackno(), tcph->flags(), tcph->hlen(), tcph->sa_length());
+      }
+      if (pt_->namchannel() != 0)
+         sprintf(pt_->nbuffer(),
+                 "%c -t " TIME_FORMAT
+                 " -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
+                 tt, Scheduler::instance().clock(), s, d, name, th->size(),
+                 iph->flowid(), th->uid(), iph->flowid(), src_nodeaddr,
+                 src_portaddr, dst_nodeaddr, dst_portaddr, seqno, flags, sname);
+      delete[]src_nodeaddr;
+      delete[]src_portaddr;
+      delete[]dst_nodeaddr;
+      delete[]dst_portaddr;
+   }
+}
+
+
+int
+            UMTSTrace::get_seqno(Packet * p)
+{
+   hdr_cmn    *th = hdr_cmn::access(p);
+   hdr_tcp    *tcph = hdr_tcp::access(p);
+   hdr_rtp    *rh = hdr_rtp::access(p);
+   hdr_rap    *raph = hdr_rap::access(p);
+   hdr_tfrc   *tfrch = hdr_tfrc::access(p);
+
+   packet_t t = th->ptype();
+   int seqno;
+
+   /* UDP's now have seqno's too */
+   if (t == PT_RTP || t == PT_CBR || t == PT_UDP || t == PT_EXP
+       || t == PT_PARETO || t == PT_COOT) {
+      seqno = rh->seqno();
+   } else if (t == PT_RAP_DATA || t == PT_RAP_ACK) {
+      seqno = raph->seqno();
+   } else if (t == PT_TCP || t == PT_ACK || t == PT_HTTP || t == PT_FTP
+              || t == PT_TELNET) {
+      seqno = tcph->seqno();
+   } else if (t == PT_TFRC) {
+      seqno = tfrch->seqno;
+   } else if (t == PT_UM || t == PT_AMDA || t == PT_AMPA || t == PT_AMBA
+              || t == PT_AMPBPA || t == PT_AMPBBA || t == PT_AMDA_H1 || t == PT_AMDA_H2 || t == PT_AMDA_H3) {
+      seqno = tcph->seqno();
+   } else {
+      seqno = -1;
+   }
+   return seqno;
+}
diff -urN ns-2.30-orig/umts/umtstrace.h ns-2.30-eu112/umts/umtstrace.h
--- ns-2.30-orig/umts/umtstrace.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/umtstrace.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: umtstrace.h,v 1.2 2004/01/20 13:29:24 simon Exp $
+ */
+
+#ifndef ns_umtstrace_h
+#define ns_umtstrace_h
+
+#include "trace.h"
+
+
+class UMTSTrace:public Trace {
+protected:
+   void        format(int tt, int s, int d, Packet * p);
+public:
+               UMTSTrace(int type):Trace(type) {
+   } static int get_seqno(Packet * p);
+};
+
+#endif
diff -urN ns-2.30-orig/umts/virtual_umtsmac.cc ns-2.30-eu112/umts/virtual_umtsmac.cc
--- ns-2.30-orig/umts/virtual_umtsmac.cc	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/virtual_umtsmac.cc	2006-10-07 22:02:13.000000000 +0307
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: virtual_umtsmac.cc,v 1.4 2004/01/20 13:29:24 simon Exp $
+ */
+
+#include "virtual_umtsmac.h"
+
+////////////////////////////UMTS MAC impl//////////////////////////
+
+
+VirtualUmtsMac::VirtualUmtsMac():Mac()
+{
+}
diff -urN ns-2.30-orig/umts/virtual_umtsmac.h ns-2.30-eu112/umts/virtual_umtsmac.h
--- ns-2.30-orig/umts/virtual_umtsmac.h	1970-01-01 03:07:04.000000000 +0307
+++ ns-2.30-eu112/umts/virtual_umtsmac.h	2006-10-07 22:02:17.000000000 +0307
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
+ * 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 must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the
+ *     distribution.
+ * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ * Contact for feedback on EURANE: eurane@ti-wmc.nl
+ * EURANE = Enhanced UMTS Radio Access Network Extensions
+ * website: http://www.ti-wmc.nl/eurane/
+ */
+
+/*
+ * $Id: virtual_umtsmac.h,v 1.2 2004/01/20 13:29:24 simon Exp $
+ */
+
+#ifndef ns_virtual_umtsmac_h
+#define ns_virtual_umtsmac_h
+
+#include "mac.h"
+
+////////////////////////////UMTS MAC//////////////////////////
+
+
+class VirtualUmtsMac:public Mac {
+public:
+   VirtualUmtsMac();
+   virtual void timeout(int tno) = 0;
+};
+
+#endif
