GSoC 2014 FFR algorithms
authorPiotr Gawlowicz <gawlowicz.p@gmail.com>
Fri, 05 Sep 2014 01:12:55 +0200
changeset 10881 dab52e61774d
parent 10880 838eb3c66675
child 10882 0121998bec84
GSoC 2014 FFR algorithms
CHANGES.html
RELEASE_NOTES
doc/models/Makefile
src/lte/doc/Makefile
src/lte/doc/source/lte-design.rst
src/lte/doc/source/lte-references.rst
src/lte/doc/source/lte-testing.rst
src/lte/doc/source/lte-user.rst
src/lte/examples/lena-distributed-ffr.cc
src/lte/examples/lena-dual-stripe.cc
src/lte/examples/lena-frequency-reuse.cc
src/lte/examples/lena-uplink-power-control.cc
src/lte/examples/wscript
src/lte/helper/lte-helper.cc
src/lte/helper/lte-helper.h
src/lte/helper/lte-hex-grid-enb-topology-helper.cc
src/lte/helper/radio-environment-map-helper.cc
src/lte/helper/radio-environment-map-helper.h
src/lte/model/cqa-ff-mac-scheduler.cc
src/lte/model/cqa-ff-mac-scheduler.h
src/lte/model/fdbet-ff-mac-scheduler.cc
src/lte/model/fdbet-ff-mac-scheduler.h
src/lte/model/fdmt-ff-mac-scheduler.cc
src/lte/model/fdmt-ff-mac-scheduler.h
src/lte/model/fdtbfq-ff-mac-scheduler.cc
src/lte/model/fdtbfq-ff-mac-scheduler.h
src/lte/model/ff-mac-scheduler.h
src/lte/model/lte-chunk-processor.cc
src/lte/model/lte-chunk-processor.h
src/lte/model/lte-enb-cphy-sap.h
src/lte/model/lte-enb-net-device.cc
src/lte/model/lte-enb-net-device.h
src/lte/model/lte-enb-phy.cc
src/lte/model/lte-enb-phy.h
src/lte/model/lte-enb-rrc.cc
src/lte/model/lte-enb-rrc.h
src/lte/model/lte-ffr-algorithm.cc
src/lte/model/lte-ffr-algorithm.h
src/lte/model/lte-ffr-distributed-algorithm.cc
src/lte/model/lte-ffr-distributed-algorithm.h
src/lte/model/lte-ffr-enhanced-algorithm.cc
src/lte/model/lte-ffr-enhanced-algorithm.h
src/lte/model/lte-ffr-rrc-sap.cc
src/lte/model/lte-ffr-rrc-sap.h
src/lte/model/lte-ffr-sap.cc
src/lte/model/lte-ffr-sap.h
src/lte/model/lte-ffr-soft-algorithm.cc
src/lte/model/lte-ffr-soft-algorithm.h
src/lte/model/lte-fr-hard-algorithm.cc
src/lte/model/lte-fr-hard-algorithm.h
src/lte/model/lte-fr-no-op-algorithm.cc
src/lte/model/lte-fr-no-op-algorithm.h
src/lte/model/lte-fr-soft-algorithm.cc
src/lte/model/lte-fr-soft-algorithm.h
src/lte/model/lte-fr-strict-algorithm.cc
src/lte/model/lte-fr-strict-algorithm.h
src/lte/model/lte-interference.cc
src/lte/model/lte-interference.h
src/lte/model/lte-rrc-header.cc
src/lte/model/lte-rrc-sap.h
src/lte/model/lte-sinr-chunk-processor.cc
src/lte/model/lte-sinr-chunk-processor.h
src/lte/model/lte-spectrum-phy.cc
src/lte/model/lte-spectrum-phy.h
src/lte/model/lte-spectrum-value-helper.cc
src/lte/model/lte-spectrum-value-helper.h
src/lte/model/lte-ue-cphy-sap.h
src/lte/model/lte-ue-phy.cc
src/lte/model/lte-ue-phy.h
src/lte/model/lte-ue-power-control.cc
src/lte/model/lte-ue-power-control.h
src/lte/model/lte-ue-rrc.cc
src/lte/model/lte-ue-rrc.h
src/lte/model/pf-ff-mac-scheduler.cc
src/lte/model/pf-ff-mac-scheduler.h
src/lte/model/pss-ff-mac-scheduler.cc
src/lte/model/pss-ff-mac-scheduler.h
src/lte/model/rem-spectrum-phy.cc
src/lte/model/rem-spectrum-phy.h
src/lte/model/rr-ff-mac-scheduler.cc
src/lte/model/rr-ff-mac-scheduler.h
src/lte/model/tdbet-ff-mac-scheduler.cc
src/lte/model/tdbet-ff-mac-scheduler.h
src/lte/model/tdmt-ff-mac-scheduler.cc
src/lte/model/tdmt-ff-mac-scheduler.h
src/lte/model/tdtbfq-ff-mac-scheduler.cc
src/lte/model/tdtbfq-ff-mac-scheduler.h
src/lte/model/tta-ff-mac-scheduler.cc
src/lte/model/tta-ff-mac-scheduler.h
src/lte/test/lte-ffr-simple.cc
src/lte/test/lte-ffr-simple.h
src/lte/test/lte-simple-spectrum-phy.cc
src/lte/test/lte-simple-spectrum-phy.h
src/lte/test/lte-test-cqi-generation.cc
src/lte/test/lte-test-cqi-generation.h
src/lte/test/lte-test-downlink-power-control.cc
src/lte/test/lte-test-downlink-power-control.h
src/lte/test/lte-test-downlink-sinr.cc
src/lte/test/lte-test-fading.cc
src/lte/test/lte-test-fdbet-ff-mac-scheduler.cc
src/lte/test/lte-test-fdmt-ff-mac-scheduler.cc
src/lte/test/lte-test-frequency-reuse.cc
src/lte/test/lte-test-frequency-reuse.h
src/lte/test/lte-test-harq.cc
src/lte/test/lte-test-interference-fr.cc
src/lte/test/lte-test-interference-fr.h
src/lte/test/lte-test-interference.cc
src/lte/test/lte-test-link-adaptation.cc
src/lte/test/lte-test-mimo.cc
src/lte/test/lte-test-pathloss-model.cc
src/lte/test/lte-test-phy-error-model.cc
src/lte/test/lte-test-rr-ff-mac-scheduler.cc
src/lte/test/lte-test-sinr-chunk-processor.cc
src/lte/test/lte-test-sinr-chunk-processor.h
src/lte/test/lte-test-tdbet-ff-mac-scheduler.cc
src/lte/test/lte-test-tdmt-ff-mac-scheduler.cc
src/lte/test/lte-test-tta-ff-mac-scheduler.cc
src/lte/test/lte-test-ue-measurements.cc
src/lte/test/lte-test-uplink-power-control.cc
src/lte/test/lte-test-uplink-power-control.h
src/lte/test/lte-test-uplink-sinr.cc
src/lte/test/reference/lte_cqi_generation.m
src/lte/test/reference/lte_frequency_reuse.m
src/lte/test/reference/lte_link_budget_interference_fr.m
src/lte/test/reference/lte_uplink_power_control.m
src/lte/test/reference/path_loss.m
src/lte/test/test-asn1-encoding.cc
src/lte/test/test-lte-antenna.cc
src/lte/test/test-lte-x2-handover-measures.cc
src/lte/test/test-lte-x2-handover.cc
src/lte/wscript
src/spectrum/doc/spectrum.rst
--- a/CHANGES.html	Thu Sep 04 23:13:41 2014 +0300
+++ b/CHANGES.html	Fri Sep 05 01:12:55 2014 +0200
@@ -63,6 +63,32 @@
        the effect of including the help string for the Attribute in the
        Usage message.
   </li>
+  <li> The GSoC 2014 project in the LTE module has brought some additional APIs:
+    <ul>
+      <li>a new abstract class LteFfrAlgorithm, which every future
+          implementation of frequency reuse algorithm should inherit from</li>
+      <li>a new SAPs: one between MAC Scheduler and FrAlgorithm, one between
+	  RRC and FrAlgorithm</li>
+      <li>new attribute to enable Uplink Power Control in LteUePhy</li>
+      <li>new LteUePowerControl class, an implementation of Uplink Power Control, which is 
+          configurable by attributes. ReferenceSignalPower is sent by eNB in SIB2. 
+          Uplink Power Control in Closed Loop Accumulative Mode is enabled by default</li>
+      <li>seven different Frequency Reuse Algorithms (each has its own attributes): </li>
+        <ul>
+          <li>LteFrNoOpAlgorithm</li>
+          <li>LteFrHardAlgorithm</li>
+          <li>LteFrStrictAlgorithm</li>
+          <li>LteFrSoftAlgorithm</li>
+          <li>LteFfrSoftAlgorithm</li>
+          <li>LteFfrEnhancedAlgorithm</li>
+          <li>LteFfrDistributedAlgorithm</li>
+        </ul>
+      <li>attribute in LteFfrAlgorithm to set FrCellTypeId which is used in automatic 
+          Frequency Reuse algorithm configuration</li>
+      <li>LteHelper has been updated with new methods related to frequency reuse algorithm: 
+          SetFfrAlgorithmType and SetFfrAlgorithmAttribute</li>
+    </ul>
+  </li>
 </ul>
 
 <h2>Changes to existing API:</h2>
@@ -72,6 +98,18 @@
   <li> The TCP socket Attribute "SlowStartThreshold" has been renamed "InitialSlowStartThreshold" to
        clarify that the effect is only on the initial value.
   </li>
+  <li> all schedulers were updated to interact with FR entity via FFR-SAP. Only PF, PSS, CQA, 
+       FD-TBFQ, TD-TBFQ schedulers supports Frequency Reuse functionality. In the beginning 
+       of scheduling process, schedulers ask FR entity for avaiable RBGs and then ask if UE 
+       can be scheduled on RB</li>
+  <li> eNB RRC interacts with FFR entity via RRC-FFR SAP</li>
+  <li> new DL-CQI generation approach was implemented. Now DL-CQI is computed from control channel as signal
+       and data channel (if received) as interference. New attribute in LteHelper was added to specify 
+       DL-CQI generation approach. New approach is default one in LteHelper </li>
+  <li> RadioEnvironmentMap can be generated for Data or Control channel and for specified RbId;
+       Data or Control channel and RbId can be configured by new attributes in RadioEnvironmentMapHelper </li>
+  <li> lte-sinr-chunk-processor refactored to lte-chunk-processor. Removed all lte-xxx-chunk-processor 
+       implementations</li>
 </ul>
 
 <h2>Changes to build system:</h2>
--- a/RELEASE_NOTES	Thu Sep 04 23:13:41 2014 +0300
+++ b/RELEASE_NOTES	Fri Sep 05 01:12:55 2014 +0200
@@ -26,6 +26,19 @@
   interfaces over emulated links via the new helper class EmuEpcHelper.
 - CommandLine can now provide a shorthand argument name for any
   Attribute.
+- Implemented support for Frequency Reuse algorithms in LTE module, as the 
+  outcome of GSoC 2014 project. 
+  The project also includes several sub-features, such as:
+   - implementation of Downlink Power Control
+   - implementation of Uplink Power Control
+   - new DL-CQI generation approach, which increases throughput if FR algorithms 
+     are used
+   - seven options of Frequency Reuse algorithms: LteFrNoOpAlgorithm, 
+     LteFrHardAlgorithm, LteFrStrictAlgorithm, LteFrSoftAlgorithm, 
+     LteFfrSoftAlgorithm, LteFfrEnhancedAlgorithm, LteFfrDistributedAlgorithm
+   - updated RadioEnvironmentMapHelper. Now RadioEnvironmentMap can be generated 
+     for Data or Control channel and for specified RbId, what is helpful when 
+     using FR algorithms
 
 Bugs fixed
 ----------
@@ -45,6 +58,8 @@
 - Bug 1961 - planetlab-tap-creator "variable set but not used"
 - Bug 1963 - AODV can tag the same packet twice (and raise an assert)
 - Bug 1967 - LL Multicast is not compressed in the right way in IPHC
+- Bug 1942 - refactoring of lte-sinr-chunk-processor -> lte-chunk-processor
+
 
 Known issues
 ------------
--- a/doc/models/Makefile	Thu Sep 04 23:13:41 2014 +0300
+++ b/doc/models/Makefile	Fri Sep 05 01:12:55 2014 +0200
@@ -176,6 +176,32 @@
 	$(SRC)/lte/doc/source/figures/fading_vehicular.png \
 	$(SRC)/lte/doc/source/figures/fading_urban_3kmph.pdf \
 	$(SRC)/lte/doc/source/figures/fading_urban_3kmph.png \
+	$(SRC)/lte/doc/source/figures/fr-enhanced-fractional-frequency-reuse-scheme.png \
+	$(SRC)/lte/doc/source/figures/fr-enhanced-fractional-frequency-reuse-scheme.pdf \
+	$(SRC)/lte/doc/source/figures/fr-full-frequency-reuse-scheme.png \
+	$(SRC)/lte/doc/source/figures/fr-full-frequency-reuse-scheme.pdf \
+	$(SRC)/lte/doc/source/figures/fr-hard-frequency-reuse-scheme.png \
+	$(SRC)/lte/doc/source/figures/fr-hard-frequency-reuse-scheme.pdf \
+	$(SRC)/lte/doc/source/figures/fr-soft-fractional-frequency-reuse-scheme.png \
+	$(SRC)/lte/doc/source/figures/fr-soft-fractional-frequency-reuse-scheme.pdf \
+	$(SRC)/lte/doc/source/figures/fr-soft-frequency-reuse-scheme-v1.png \
+	$(SRC)/lte/doc/source/figures/fr-soft-frequency-reuse-scheme-v1.pdf \
+	$(SRC)/lte/doc/source/figures/fr-soft-frequency-reuse-scheme-v2.png \
+	$(SRC)/lte/doc/source/figures/fr-soft-frequency-reuse-scheme-v2.pdf \
+	$(SRC)/lte/doc/source/figures/fr-strict-frequency-reuse-scheme.png \
+	$(SRC)/lte/doc/source/figures/fr-strict-frequency-reuse-scheme.pdf \
+	$(SRC)/lte/doc/source/figures/ffr-distributed-scheme.png \
+	$(SRC)/lte/doc/source/figures/ffr-distributed-scheme.pdf \
+	$(SRC)/lte/doc/source/figures/lte-fr-soft-1-rem.png \
+	$(SRC)/lte/doc/source/figures/lte-fr-soft-1-rem.pdf \
+	$(SRC)/lte/doc/source/figures/lte-ffr-soft-2-spectrum-trace.png \
+	$(SRC)/lte/doc/source/figures/lte-ffr-soft-2-spectrum-trace.pdf \
+	$(SRC)/lte/doc/source/figures/lte-fr-hard-1-rem.png \
+	$(SRC)/lte/doc/source/figures/lte-fr-hard-1-rem.pdf \
+	$(SRC)/lte/doc/source/figures/lte-fr-hard-2-rem.png \
+	$(SRC)/lte/doc/source/figures/lte-fr-hard-2-rem.pdf \
+	$(SRC)/lte/doc/source/figures/lte-fr-hard-3-rem.png \
+	$(SRC)/lte/doc/source/figures/lte-fr-hard-3-rem.pdf \
 	$(SRC)/lte/doc/source/figures/MCS_1_4.pdf \
 	$(SRC)/lte/doc/source/figures/MCS_1_4.png \
 	$(SRC)/lte/doc/source/figures/MCS_5_8.pdf \
@@ -200,6 +226,10 @@
 	$(SRC)/lte/doc/source/figures/MCS_16_test.pdf \
 	$(SRC)/lte/doc/source/figures/miesm_scheme.pdf \
 	$(SRC)/lte/doc/source/figures/miesm_scheme.png \
+	$(SRC)/lte/doc/source/figures/lte-dl-power-control.png \
+	$(SRC)/lte/doc/source/figures/lte-dl-power-control.pdf \
+	$(SRC)/lte/doc/source/figures/lte-ffr-scheduling.png \
+	$(SRC)/lte/doc/source/figures/lte-ffr-scheduling.pdf \
 	$(SRC)/lte/doc/source/figures/lte-handover-campaign-rem.pdf \
 	$(SRC)/lte/doc/source/figures/lte-handover-campaign-rem.png \
 	$(SRC)/lte/doc/source/figures/lte-legacy-handover-algorithm.pdf \
--- a/src/lte/doc/Makefile	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/doc/Makefile	Fri Sep 05 01:12:55 2014 +0200
@@ -108,6 +108,22 @@
 	$(FIGURES)/fading_pedestrian.pdf \
 	$(FIGURES)/fading_vehicular.pdf \
 	$(FIGURES)/fading_urban_3kmph.pdf \
+	$(FIGURES)/fr-enhanced-fractional-frequency-reuse-scheme.png \
+	$(FIGURES)/fr-enhanced-fractional-frequency-reuse-scheme.pdf \
+	$(FIGURES)/fr-full-frequency-reuse-scheme.png \
+	$(FIGURES)/fr-full-frequency-reuse-scheme.pdf \
+	$(FIGURES)/fr-hard-frequency-reuse-scheme.png \
+	$(FIGURES)/fr-hard-frequency-reuse-scheme.pdf \
+	$(FIGURES)/fr-soft-fractional-frequency-reuse-scheme.png \
+	$(FIGURES)/fr-soft-fractional-frequency-reuse-scheme.pdf \
+	$(FIGURES)/fr-soft-frequency-reuse-scheme-v1.png \
+	$(FIGURES)/fr-soft-frequency-reuse-scheme-v1.pdf \
+	$(FIGURES)/fr-soft-frequency-reuse-scheme-v2.png \
+	$(FIGURES)/fr-soft-frequency-reuse-scheme-v2.pdf \
+	$(FIGURES)/fr-strict-frequency-reuse-scheme.png \
+	$(FIGURES)/fr-strict-frequency-reuse-scheme.pdf \
+	$(FIGURES)/ffr-distributed-scheme.png \
+	$(FIGURES)/ffr-distributed-scheme.pdf \
 	$(FIGURES)/MCS_1_4.pdf \
 	$(FIGURES)/MCS_1_4.png \
 	$(FIGURES)/MCS_5_8.pdf \
@@ -130,6 +146,20 @@
 	$(FIGURES)/MCS_12_test.pdf \
 	$(FIGURES)/MCS_16_test.png \
 	$(FIGURES)/MCS_16_test.pdf \
+	$(FIGURES)/lte-dl-power-control.png \
+	$(FIGURES)/lte-dl-power-control.pdf \
+	$(FIGURES)/lte-fr-soft-1-rem.png \
+	$(FIGURES)/lte-fr-soft-1-rem.pdf \
+	$(FIGURES)/lte-ffr-soft-2-spectrum-trace.png \
+	$(FIGURES)/lte-ffr-soft-2-spectrum-trace.pdf \
+	$(FIGURES)/lte-fr-hard-1-rem.png \
+	$(FIGURES)/lte-fr-hard-1-rem.pdf \
+	$(FIGURES)/lte-fr-hard-2-rem.png \
+	$(FIGURES)/lte-fr-hard-2-rem.pdf \
+	$(FIGURES)/lte-fr-hard-3-rem.png \
+	$(FIGURES)/lte-fr-hard-3-rem.pdf \
+	$(FIGURES)/lte-ffr-scheduling.png \
+	$(FIGURES)/lte-ffr-scheduling.pdf \
 	$(FIGURES)/lte-phy-interference.png \
 	$(FIGURES)/lte-phy-interference.pdf \
 	$(FIGURES)/helpers.png \
--- a/src/lte/doc/source/lte-design.rst	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/doc/source/lte-design.rst	Fri Sep 05 01:12:55 2014 +0200
@@ -503,7 +503,15 @@
 of periodic wideband CQI (i.e., a single value of channel state that is deemed representative of all RBs
 in use) and inband CQIs (i.e., a set of value representing the channel state for each RB).
 
-In downlink, the CQI feedbacks are currently evaluated according to the SINR perceived by control channel (i.e., PDCCH + PCFIC) in order to have an estimation of the interference when all the eNB are transmitting simultaneously. In uplink, two types of CQIs are implemented:
+In downlink, the CQI feedbacks can be generated in two different ways.
+First one is legacy approach and CQI are evaluated according to the SINR perceived by control channel (i.e., PDCCH + PCFIC) in order to have an estimation of the interference when all the eNB are transmitting simultaneously. 
+Second approach was created for better utilization of data channel resources, when using Frequency Reuse algorithms.
+Frequency Reuse algorithms are applied only to PDSCH and they can reduce inter-cell interferences only during PDSCH duration. Since in legacy approach CQI feedback is generated from control channels, it does not allow to use higher MCS for data channels and to achieve any gain in throughput. Generation CQI feedback only from data channels would be the best option. Unfortunately is impossible solution, because PDSCH is be sent only if there is data to be sent, and CQI needs to be generated every TTI. Some mixed approach was implemented. CQI are generated from control channels as signal and data channels (if received) as interference. It there is no transmission in data channel, CQI is generated only from control channels, as in legacy solution. 
+To switch between this two CQI generation approaches, ``LteHelper::UsePdschForCqiGeneration`` needs to be configured: false for first approach and true for second approach (true is default value)::
+
+   Config::SetDefault ("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue (true));
+
+In uplink, two types of CQIs are implemented:
 
  - SRS based, periodically sent by the UEs.
  - PUSCH based, calculated from the actual transmitted data.
@@ -542,7 +550,8 @@
 Let :math:`f_c` denote the  LTE Absolute Radio Frequency Channel Number, which
 identifies the carrier frequency on a 100 kHz raster; furthermore, let :math:`B` be
 the Transmission Bandwidth Configuration in number of Resource Blocks. For every
-pair :math:`(f_c,B)` used in the simulation we define a corresponding SpectrumModel using the functionality provided by the :ref:`sec-spetrum-module` .
+pair :math:`(f_c,B)` used in the simulation we define a corresponding SpectrumModel using 
+the functionality provided by the :ref:`sec-spectrum-module` .
 model using the Spectrum framework described
 in [Baldo2009]_.  :math:`f_c` and :math:`B` can be configured for every eNB instantiated
 in the simulation; hence, each eNB can use a different spectrum model. Every UE
@@ -690,7 +699,7 @@
 Integration of the BLER curves in the ns-3 LTE module
 -----------------------------------------------------
 
-The model implemented uses the curves for the LSM of the recently LTE PHY Error Model released in the ns3 community by the Signet Group [PaduaPEM]_ and the new ones generated for different CB sizes. The ``LteSpectrumPhy`` class is in charge of evaluating the TB BLER thanks to the methods provided by the ``LteMiErrorModel`` class, which is in charge of evaluating the TB BLER according to the vector of the perceived SINR per RB, the MCS and the size in order to proper model the segmentation of the TB in CBs. In order to obtain the vector of the perceived SINR two instances of ``LtePemSinrChunkProcessor`` (child of ``LteSinrChunkProcessor`` dedicated to evaluate the SINR for obtaining physical error performance) have been attached to UE downlink and eNB uplink ``LteSpectrumPhy`` modules for evaluating the error model distribution respectively of PDSCH (UE side) and ULSCH (eNB side).
+The model implemented uses the curves for the LSM of the recently LTE PHY Error Model released in the ns3 community by the Signet Group [PaduaPEM]_ and the new ones generated for different CB sizes. The ``LteSpectrumPhy`` class is in charge of evaluating the TB BLER thanks to the methods provided by the ``LteMiErrorModel`` class, which is in charge of evaluating the TB BLER according to the vector of the perceived SINR per RB, the MCS and the size in order to proper model the segmentation of the TB in CBs. In order to obtain the vector of the perceived SINR two instances of ``LtePemSinrChunkProcessor`` (child of ``LteChunkProcessor`` dedicated to evaluate the SINR for obtaining physical error performance) have been attached to UE downlink and eNB uplink ``LteSpectrumPhy`` modules for evaluating the error model distribution respectively of PDSCH (UE side) and ULSCH (eNB side).
 
 The model can be disabled for working with a zero-losses channel by setting the ``PemEnabled`` attribute of the ``LteSpectrumPhy`` class (by default is active). This can be done according to the standard ns3 attribute system procedure, that is::
 
@@ -3554,6 +3563,541 @@
         \clearpage
 
 
+-------------
+Power Control
+-------------
+This section describes the ns-3 implementation of Downlink and Uplink Power Control.
+
+Downlink Power Control
+++++++++++++++++++++++
+
+Since some of Frequency Reuse Algorithms require Downlink Power Control, 
+this feature was also implemented in ns-3. 
+
+.. _fig-lte-downlik-power-control:
+ 
+.. figure:: figures/lte-dl-power-control.*
+   :align: center
+
+   Sequence diagram of Downlink Power Control
+
+
+Figure :ref:`fig-lte-downlik-power-control` shows the sequence diagram of 
+setting downlink P_A value for UE, highlighting the interactions between 
+the RRC and the other entities. FR algorithm triggers RRC to change P_A values 
+for UE. Then RRC starts RrcConnectionReconfiguration function to inform UE 
+about new configuration. After successful RrcConnectionReconfiguration, RRC 
+can set P_A value for UE by calling function SetPa from CphySap, value is 
+saved in new map m_paMap which contain P_A values for each UE served by eNb.
+
+When LteEnbPhy starts new subframe, DCI control messages are processed to get 
+vector of used RBs. Now also GeneratePowerAllocationMap(uint16_t rnti, int rbId) 
+function is also called. This function check P_A value for UE, generate power 
+for each RB and store it in m_dlPowerAllocationMap. Then this map is used by 
+CreateTxPowerSpectralDensityWithPowerAllocation function to create 
+Ptr<SpectrumValue> txPsd.
+
+PdschConfigDedicated (TS 36.331, 6.3.2 PDSCH-Config) was added in 
+LteRrcSap::PhysicalConfigDedicated struct, which is used in 
+RrcConnectionReconfiguration process.
+
+Uplink Power Control
+++++++++++++++++++++++
+
+Uplink power control controls the transmit power of the different uplink physical 
+channels. This functionality is described in 3GPP TS 36.213 section 5.
+
+Uplink Power Control is enabled by default, and can be disabled by attribute system::
+
+   Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
+
+Two Uplink Power Control mechanisms are implemented:
+
+ * Open Loop Uplink Power Control: the UE transmission power depends on estimation of
+   the downlink path-loss and channel configuration
+ * Closed Loop Uplink Power Control: as in Open Loop, in addition eNB can control the UE
+   transmission power by means of explicit Transmit Power Control TPC commands transmitted 
+   in the downlink. 
+
+To switch between these two mechanism types, one should change parameter::
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+
+By default, Closed Loop Power Control is enabled.
+
+
+Two modes of Closed Loop Uplink Power Control are available: 
+ * Absolute mode: TxPower is computed with absolute TPC values
+ * Accumulative mode: TxPower is computed with accumulated TPC values
+
+To switch between these two modes, one should change parameter::
+
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (true));
+
+By default, Accumulation Mode is enabled and TPC commands in DL-DCI are set by all schedulers to 1, 
+what is mapped to value of 0 in Accumulation Mode. 
+
+
+.. _sec-uplink-power-control-pusch:
+
+Uplink Power Control for PUSCH
+------------------------------
+
+The setting of the UE Transmit power for a Physical Uplink Shared Channel (PUSCH) transmission 
+is defined as follows:
+
+ * If the UE transmits PUSCH without a simultaneous PUCCH for the serving cell :math:`c`, then the 
+   UE transmit power :math:`P_{PUSCH,c}(i)` for PUSCH transmission in subframe :math:`i` for the 
+   serving cell :math:`c` is given by:
+
+   .. math::
+
+      P_{PUSCH,c}(i)=\min\begin{Bmatrix}
+                     P_{CMAX,c}(i)\\ 
+                     10\log_{10}(M_{PUSCH,c}(i))+ P_{O\_PUSCH,c}(j) 
+                     + \alpha_{c} (j) * PL_{c} + \Delta_{TF,c}(i) + f_{c}(i)
+                     \end{Bmatrix} [dBm]
+
+ * If the UE transmits PUSCH simultaneous with PUCCH for the serving cell :math:`c`, then the UE 
+   transmit power :math:`P_{PUSCH,c}(i)` for the PUSCH transmission in subframe :math:`i` for 
+   the serving cell :math:`c` is given by:
+
+   .. math::
+
+      P_{PUSCH,c}(i)=\min\begin{Bmatrix}
+                     10\log_{10}(\hat{P}_{CMAX,c}(i) - \hat{P}_{PUCCH}(i))\\ 
+                     10\log_{10}(M_{PUSCH,c}(i))+ P_{O\_PUSCH,c}(j) 
+                     + \alpha_{c} (j) * PL_{c} + \Delta_{TF,c}(i) + f_{c}(i)
+                     \end{Bmatrix} [dBm]
+
+   Since Uplink Power Control for PUCCH is not implemented, this case is not implemented as well.
+
+ * If the UE is not transmitting PUSCH for the serving cell :math:`c`, for the accumulation of 
+   TPC command received with DCI format 3/3A for PUSCH, the UE shall assume that the UE transmit 
+   power :math:`P_{PUSCH,c}(i)` for the PUSCH transmission in    subframe :math:`i` for the serving 
+   cell :math:`c` is computed by
+
+   .. math::
+
+      P_{PUSCH,c}(i)=\min\begin{Bmatrix}
+                     {P}_{CMAX,c}(i)\\ 
+                     P_{O\_PUSCH,c}(1) + \alpha_{c} (1) * PL_{c} + f_{c}(i)
+                     \end{Bmatrix} [dBm]
+
+where:
+ * :math:`P_{CMAX,c}(i)` is the configured UE transmit power defined in 3GPP 36.101. Table 6.2.2-1
+   in subframe :math:`i` for serving cell :math:`c` and :math:`\hat{P}_{CMAX,c}(i)` is the linear 
+   value of :math:`P_{CMAX,c}(i)`. Default value for :math:`P_{CMAX,c}(i)` is 23 dBm
+
+ * :math:`M_{PUSCH,c}(i)` is the bandwidth of the PUSCH resource assignment expressed in number 
+   of resource blocks valid for subframe :math:`i` and serving cell :math:`c` .
+
+ * :math:`P_{O\_PUSCH,c}(j)` is a parameter composed of the sum of a component :math:`P_{O\_NOMINAL\_PUSCH,c}(j)`
+   provided from higher layers for :math:`j={0,1}` and a component :math:`P_{O\_UE\_PUSCH,c}(j)` provided by higher 
+   layers for :math:`j={0,1}` for serving cell :math:`c`. SIB2 message needs to be extended to carry these two 
+   components, but currently they can be set via attribute system::
+
+      Config::SetDefault ("ns3::LteUePowerControl::PoNominalPusch", IntegerValue (-90));
+      Config::SetDefault ("ns3::LteUePowerControl::PoUePusch", IntegerValue (7));
+
+ * :math:`\alpha_{c} (j)` is a 3-bit parameter provided by higher layers for serving cell :math:`c`. 
+   For :math:`j=0,1`,   :math:`\alpha_c \in \left \{ 0, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 \right \}` 
+   For :math:`j=2`,   :math:`\alpha_{c} (j) = 1`. 
+   This parameter is configurable by attribute system::
+
+      Config::SetDefault ("ns3::LteUePowerControl::Alpha", DoubleValue (0.8));
+
+ * :math:`PL_{c}` is the downlink pathloss estimate calculated in the UE for serving cell :math:`c` in dB 
+   and :math:`PL_{c} = referenceSignalPower – higher layer filtered RSRP`, where :math:`referenceSignalPower`
+   is provided by higher layers and RSRP. :math:`referenceSignalPower` is provided in SIB2 message
+
+ * :math:`\Delta_{TF,c}(i) = 10\log_{10}((2^{BPRE\cdot K_s}-1)\cdot\beta_{offset}^{PUSCH} )` for :math:`K_{s} = 1.25`
+   and :math:`\Delta_{TF,c}(i) = 0` for :math:`K_{s} = 0`. Only second case is implemented.
+
+ * :math:`f_{c}(i)` is component of Closed Loop Power Control. It is the current PUSCH power control
+   adjustment state for serving cell :math:`c`. 
+
+   If Accumulation Mode is enabled :math:`f_{c}(i)` is given by:
+
+      .. math::
+
+         f_{c}(i) = f_{c}(i-1) + \delta_{PUSCH,c}(i - K_{PUSCH})
+
+   where: :math:`\delta_{PUSCH,c}` is a correction value, also referred to as a TPC command and is included 
+   in PDCCH with DCI; :math:`\delta_{PUSCH,c}(i - K_{PUSCH})` was signalled on PDCCH/EPDCCH with DCI for
+   serving cell :math:`c` on subframe :math:`i − K_{PUSCH}`; :math:`K_{PUSCH} = 4` for FDD.
+
+   If UE has reached :math:`P_{CMAX,c}(i)` for serving cell :math:`c`, positive TPC commands for serving cell
+   :math:`c` are not be accumulated. If UE has reached minimum power, negative TPC commands are not be accumulated.
+   Minimum UE power is defined in TS36.101 section 6.2.3.  Default value is -40 dBm.
+
+   If Accumulation Mode is not enabled :math:`f_{c}(i)` is given by:
+      
+      .. math::
+
+         f_{c}(i) = \delta_{PUSCH,c}(i - K_{PUSCH})
+
+   where: :math:`\delta_{PUSCH,c}` is a correction value, also referred to as a TPC command and is included 
+   in PDCCH with DCI; :math:`\delta_{PUSCH,c}(i - K_{PUSCH})` was signalled on PDCCH/EPDCCH with DCI for
+   serving cell :math:`c` on subframe :math:`i − K_{PUSCH}`; :math:`K_{PUSCH} = 4` for FDD.
+
+   Mapping of TPC Command Field in DCI format 0/3/4 to absolute and accumulated :math:`\delta_{PUSCH,c}`
+   values is defined in TS36.231 section 5.1.1.1 Table 5.1.1.1-2
+
+
+Uplink Power Control for PUCCH
+------------------------------
+
+Since all uplink control messages are an ideal messages and do not consume any radio resources, 
+Uplink Power Control for PUCCH is not needed and it is not implemented.
+
+
+Uplink Power Control for SRS
+------------------------------
+
+The setting of the UE Transmit power :math:`P_{SRS}` for the SRS transmitted on subframe :math:`i` 
+for serving cell :math:`c` is defined by
+
+   .. math::
+
+      P_{PUSCH,c}(i)=\min\begin{Bmatrix}
+                     {P}_{CMAX,c}(i)\\ 
+                     P_{SRS\_OFFSET,c}(m) + 10\log_{10}(M_{SRS,c})+ 
+                     P_{O\_PUSCH,c}(j) + \alpha_{c}(j) * PL_{c} + f_{c}(i)
+                     \end{Bmatrix} [dBm]
+
+
+where:
+ * :math:`P_{CMAX,c}(i)` is the configured UE transmit power defined in 3GPP 36.101. Table 6.2.2-1. 
+   Default value for :math:`P_{CMAX,c}(i)` is 23 dBm
+
+ * :math:`P_{SRS\_OFFSET,c}(m)` is semi-statically configured by higher layers for :math:`m=0,1` for 
+   serving cell :math:`c` . For SRS transmission given trigger type 0 then :math:`m=0,1` and for SRS 
+   transmission given trigger type 1 then :math:`m=1`.
+   For :math:`K_{s} = 0` P_Srs_Offset_Value is computed with equation:
+
+   .. math::
+
+      P_{SRS\_OFFSET,c}(m)value = -10.5 + P_{SRS\_OFFSET,c}(m) * 1.5 [dBm]
+
+   This parameter is configurable by attribute system::
+
+      Config::SetDefault ("ns3::LteUePowerControl::PsrsOffset", IntegerValue (7));
+
+ * :math:`M_{SRS,c}` is the bandwidth of the SRS transmission in subframe :math:`i` for serving 
+   cell :math:`c` expressed in number of resource blocks. In current implementation SRS is sent 
+   over entire UL bandwidth. 
+
+ * :math:`f_{c}(i)` is the current PUSCH power control adjustment state for serving cell :math:`c`,
+   as defined in    :ref:`sec-uplink-power-control-pusch`
+
+ * :math:`P_{O\_PUSCH,c}(j)` and :math:`\alpha_{c}(j)` are parameters as defined in
+   :ref:`sec-uplink-power-control-pusch`, where :math:`j = 1` .
+
+--------------------------
+Fractional Frequency Reuse
+--------------------------
+
+
+Overview
+++++++++
+
+This section describes the ns-3 support for Fractional Frequency Reuse 
+algorithms. All implemented algorithms are described in [ASHamza2013]_.
+Currently 7 FR algorithms are implemented:
+
+ * ``ns3::LteFrNoOpAlgorithm``
+ * ``ns3::LteFrHardAlgorithm``
+ * ``ns3::LteFrStrictAlgorithm``
+ * ``ns3::LteFrSoftAlgorithm``
+ * ``ns3::LteFfrSoftAlgorithm``
+ * ``ns3::LteFfrEnhancedAlgorithm``
+ * ``ns3::LteFfrDistributedAlgorithm``
+
+
+New LteFfrAlgorithm class was created and it is a abstract class for 
+Frequency Reuse algorithms implementation. Also, two new SAPs between 
+FR-Scheduler and FR-RRC were added. 
+
+
+.. _fig-lte-ffr-scheduling:
+ 
+.. figure:: figures/lte-ffr-scheduling.*
+   :align: center
+
+   Sequence diagram of Scheduling with FR algorithm
+
+Figure :ref:`fig-lte-ffr-scheduling` shows the sequence diagram of 
+scheduling process with FR algorithm. In the beginning of scheduling 
+process, scheduler asks FR entity for avaiable RBGs. According to 
+implementation FR returns all RBGs available in cell or filter them based 
+on its policy. Then when trying to assign some RBG to UE, scheduler asks FR 
+entity if this RBG is allowed for this UE. When FR returns true, scheduler 
+can assign this RBG to this UE, if not scheduler is checking another RBG 
+for this UE. Again, FR response depends on implementation and policy applied 
+to UE.
+
+
+Supported FR algorithms
+++++++++++++++++++++++++
+
+No Frequency Reuse
+------------------
+The NoOp FR algorithm (LteFrNoOpAlgorithm class) is implementation of 
+Full Frequency Reuse scheme, that means no frequency partitioning is performed 
+between eNBs of the same network (frequency reuse factor, FRF equals 1). eNBs 
+uses entire system bandwidth and transmit with uniform power over all RBGs. It 
+is the simplest scheme and is the basic way of operating an LTE network. This 
+scheme allows for achieving the high peak data rate. But from the other hand, 
+due to heavy interference levels from neighbouring cells, cell-edge users 
+performance is greatly limited. 
+
+Figure :ref:`fig-lte-full-frequency-reuse-scheme` below presents frequency and 
+power plan for Full Frequency Reuse scheme.
+
+.. _fig-lte-full-frequency-reuse-scheme:
+ 
+.. figure:: figures/fr-full-frequency-reuse-scheme.*
+   :scale: 40 %
+   :align: center
+
+   Full Frequency Reuse scheme 
+
+In ns-3, the NoOp FR algorithm always allows scheduler to use full bandwidth 
+and allows all UEs to use any RBG. It simply does nothing new (i.e. it does not 
+limit eNB bandwidth, FR algorithm is disabled), it is the simplest implementation 
+of FrAlgorithm class and is installed in eNb by default. 
+
+.. _sec-fr-hard-algorithm:
+
+Hard Frequency Reuse
+--------------------
+The Hard Frequency Reuse algorithm provides the simplest scheme which allows to 
+reduce inter-cell interference level. In this scheme whole frequency bandwidth is 
+divided into few (typically 3, 4, or 7) disjoint sub-bands. Adjacent eNBs are 
+allocated with different sub-band. Frequency reuse factor equals the number 
+of sub-bands. This scheme allows to significanlty reduce ICI at the cell edge, 
+so the performance of cell-users is improved. But due to the fact, that each 
+eNB uses only one part of whole bandwidth, peak data rate level is also reduced 
+by the factor equal to the reuse factor.
+
+Figure :ref:`fig-lte-hard-frequency-reuse-scheme` below presents frequency and 
+power plan for Hard Frequency Reuse scheme.
+
+.. _fig-lte-hard-frequency-reuse-scheme:
+ 
+.. figure:: figures/fr-hard-frequency-reuse-scheme.*
+   :scale: 40 %
+   :align: center
+
+   Hard Frequency Reuse scheme 
+
+In our implementation, the Hard FR algorithm has only vector of RBGs available 
+for eNB and pass it to MAC Scheduler during scheduling functions. When scheduler 
+ask, if RBG is allowed for specific UE it allways return true.
+
+Strict Frequency Reuse
+----------------------
+Strict Frequency Reuse scheme is combination of Full and Hard Frequency Reuse 
+schemes. It consists of dividing the system bandwidth into two parts which will 
+have different frequency reuse. One common sub-band of the system bandwidth is 
+used in each cell interior (frequency reuse-1), while the other part of the 
+bandwidth is divided among the neighboring eNBs as in hard frequency reuse 
+(frequency reuse-N, N>1), in order to create one sub-band with a low inter-cell 
+interference level in each sector. Center UEs will be granted with the fully-reused 
+frequency chunks, while cell-edge UEs with ortogonal chunks. It means that interior 
+UEs from one cell do not share any spectrum with edge UEs from second cell, which 
+reduces interference for both. As can be noticed, Strict FR requires a total of 
+N + 1 sub-bands, and allows to achieve RFR in the middle between 1 and 3.
+
+Figure :ref:`fig-lte-strict-frequency-reuse-scheme` below presents frequency and 
+power plan for Strict Frequency Reuse scheme with a cell-edge reuse factor of N = 3.
+
+.. _fig-lte-strict-frequency-reuse-scheme:
+ 
+.. figure:: figures/fr-strict-frequency-reuse-scheme.*
+   :scale: 40 %
+   :align: center
+
+   Strict Frequency Reuse scheme 
+
+In our implementation, Strict FR algorithm has two maps, one for each sub-band. 
+If UE can be served within private sub-band, its RNTI is added to m_privateSubBandUe 
+map. If UE can be served within common sub-band, its RNTI is added to 
+m_commonSubBandUe map. Strict FR algorithm needs to decide within which sub-band 
+UE should be served. It uses UE measurements provided by RRB and compare them 
+with signal quality threshold (this parameter can be easily tuned by attribute 
+mechanism). Threshold has influence on interior to cell radius ratio.
+
+
+Soft Frequency Reuse
+--------------------
+In Soft Frequency Reuse (SFR) scheme each eNb transmits over the entire system 
+bandwidth, but there are two sub-bands, within UEs are served with different power 
+level. Since cell-center UEs share the bandwidth with neighboring cells, they 
+usually transmit at lower power level than the cell-edge UEs. SFR is more bandwidth 
+efficient than Strict FR, because it uses entire system bandwidth, but it also 
+results in more interference to both cell interior and edge users.
+
+There are two possible versions of SFR scheme:
+
+ * In first version, the sub-band dedicated for the cell-edge UEs may also be used 
+   by the cell-center UEs but with reduced power level and only if it is not occupied 
+   by the cell-edge UEs. Cell-center sub-band is available to the centre UEs only. 
+   Figure :ref:`fig-lte-soft-frequency-reuse-scheme-v1` below presents frequency and 
+   power plan for this version of Soft Frequency Reuse scheme.
+
+   .. _fig-lte-soft-frequency-reuse-scheme-v1:
+ 
+   .. figure:: figures/fr-soft-frequency-reuse-scheme-v1.*
+      :scale: 40 %
+      :align: center
+
+      Soft Frequency Reuse scheme version 1 
+
+ * In second version, cell-center UEs do not have access to cell-edge sub-band. 
+   In this way, each cell can use the whole system bandwidth while reducing the 
+   interference to the neighbors cells. From the other hand, lower ICI level at 
+   the cell-edge is achieved at the expense of lower spectrum utilization. 
+   Figure :ref:`fig-lte-soft-frequency-reuse-scheme-v2` below presents frequency 
+   and power plan for this version of Soft Frequency Reuse scheme. 
+
+   .. _fig-lte-soft-frequency-reuse-scheme-v2:
+ 
+   .. figure:: figures/fr-soft-frequency-reuse-scheme-v2.*
+      :scale: 40 %
+      :align: center
+
+      Soft Frequency Reuse scheme version 2
+
+SFR algorithm maintain two maps. If UE should be served with lower power level, 
+its RNTI is added to m_lowPowerSubBandUe map. If UE should be served with higher 
+power level, its RNTI is added to m_highPowerSubBandUe map. To decide with which 
+power level UE should be served SFR algorithm utilize UE measurements, and 
+compares them to threshold. Signal quality threshold and PdschConfigDedicated 
+(i.e. P_A value) for inner and outer area can be configured by attributes system. 
+SFR utilizes Downlink Power Control described here.
+
+
+Soft Fractional Frequency Reuse
+-------------------------------
+
+Soft Fractional Frequency Reuse (SFFR) is an combination of Strict and Soft 
+Frequency Reuse schemes. While Strict FR do not use the subbands allocated 
+for outer region in the adjacent cells, soft FFR uses these subbands for the 
+inner UEs with low transmit power. As a result, the SFFR, like SFR, use the 
+subband with high transmit power level and with low transmit power level. 
+Unlike the Soft FR and like Strict FR, the Soft FFR uses the common sub-band 
+which can enhance the throughput of the inner users.
+
+Figure :ref:`fig-lte-soft-fractional-frequency-reuse-scheme` below presents 
+frequency and power plan for Soft Fractional Frequency Reuse.
+
+.. _fig-lte-soft-fractional-frequency-reuse-scheme:
+ 
+.. figure:: figures/fr-soft-fractional-frequency-reuse-scheme.*
+   :scale: 40 %
+   :align: center
+
+   Soft Fractional Fractional Frequency Reuse scheme
+
+Enhanced Fractional Frequency Reuse
+-----------------------------------
+
+Enhanced Fractional Frequency Reuse (EFFR) described in [ZXie2009]_ defines 3 
+cell-types for directly neighboring cells in a cellular system, and reserves 
+for each cell-type a part of the whole frequency band named `Primary Segment`,
+which among different type cells should be orthogonal. The remaining subchannels 
+constitute the `Secondary Segment`. The `Primary Segment` of a cell-type is 
+at the same time a part of the `Secondary Segments` belonging to the other two 
+cell-types. Each cell can occupy all subchannels of its `Primary Segment` at 
+will, whereas only a part of subchannels in the `Secondary Segment` can be used 
+by this cell in an interference-aware manner.The `Primary Segment` of each cell 
+is divided into a reuse-3 part and reuse-1 part. The reuse-1 part can be reused 
+by all types of cells in the system, whereas reuse-3 part can only be exclusively 
+reused by other same type cells( i.e. the reuse-3 subchannels cannot be reused 
+by directly neighboring cells). On the `Secondary Segment` cell acts as a guest, 
+and occupying secondary subchannels is actually reuse the primary subchannels 
+belonging to the directly neighboring cells, thus reuse on the `Secondary Segment` 
+by each cell should conform to two rules:
+
+ * monitor before use
+ * resource reuse based on SINR estimation
+
+Each cell listens on every secondary subchannel all the time. And before occupation, 
+it makes SINR evaluation according to the gathered channel quality information (CQI) 
+and chooses resources with best estimation values for reuse. If CQI value for RBG is 
+above configured threshold for some user, transmission for this user can be performed 
+using this RBG.
+
+In [ZXie2009]_ scheduling process is described, it consist of three steps and two 
+scheduling polices. Since none of currently implemented schedulers allow for
+this behaviour, some simplification were applied. In our implementation reuse-1 
+subchannels can be used only by cell center users. Reuse-3 subchannels can be used by
+edge users, and only if there is no edge user, transmission for cell center users can
+be served in reuse-3 subchannels.
+
+Figure :ref:`fig-lte-enhanced-fractional-frequency-reuse-scheme` below presents 
+frequency and power plan for Enhanced Fractional Frequency Reuse.
+
+.. _fig-lte-enhanced-fractional-frequency-reuse-scheme:
+ 
+.. figure:: figures/fr-enhanced-fractional-frequency-reuse-scheme.*
+   :scale: 40 %
+   :align: center
+
+   Enhanced Fractional Fractional Frequency Reuse scheme
+
+
+Distributed Fractional Frequency Reuse
+--------------------------------------
+
+This Distributed Fractional Frequency Reuse Algorithm was presented in [DKimura2012]_. It 
+automatically optimizes cell-edge sub-bands by focusing on user distribution (in particular,
+receive-power distribution). This algorithm adaptively selects RBs for cell-edge sub-band on 
+basis of coordination information from adjecent cells and notifies the base stations of the 
+adjacent cells, which RBs it selected to use in edge sub-band. The base station of each cell 
+uses the received information and the following equation to compute cell-edge-band metric 
+:math:`A_{k}` for each RB.
+
+.. math::
+
+   A_{k} = \sum_{j\in J}w_{j}X_{j,k}
+
+where :math:`J` is a set of neighbor cells, :math:`X_{j,k}=\{0,1\}` is the RNTP from the :math:`j`-th
+neighbor cell. It takes a value of 1 when the :math:`k`-th RB in the :math:`j`-th neighbor cell is used 
+as a cell-edge sub-band and 0 otherwise. The symbol :math:`w_{j}` denotes weight with respect to adjacent 
+cell :math:`j`, that is, the number of users for which the difference between the power of the signal 
+received from the serving cell :math:`i` and the power of the signal received from the adjacent cell :math:`j`
+is less than a threshold value (i.e., the number of users near the cell edge in the service cell). A large 
+received power difference means that cell-edge users in the :math:`i`-th cell suffer strong interference 
+from the :math:`j`-th cell.
+
+The RB for which metric :math:`A_{k}` is smallest is considered to be least affected by interference from 
+another cell. Serving cell selects a configured number of RBs as cell-edge sub-band in ascending order 
+of :math:`A_{k}`. As a result, the RBs in which a small number of cell-edge users receive high
+interference from adjacent base stations are selected. 
+
+The updated RNTP is then sent to all the neighbor cells. In order to avoid the meaningless oscillation 
+of cell-edge-band selection, a base station ignores an RNTP from another base station that has larger 
+cell ID than the base station. 
+
+Repeating this process across all cells enables the allocation of RBs to cell-edge areas to be optimized 
+over the system and to be adjusted with changes in user distribution.
+
+Figure :ref:`fig-lte-distributed-fractional-frequency-reuse-scheme` below presents 
+sequence diagram of Distributed Fractional Frequency Reuse Scheme.
+
+.. _fig-lte-distributed-fractional-frequency-reuse-scheme:
+ 
+.. figure:: figures/ffr-distributed-scheme.*
+   :scale: 100 %
+   :align: center
+
+   Sequence diagram of Distributed Frequency Reuse Scheme
+
+
 -------
 Helpers
 -------
--- a/src/lte/doc/source/lte-references.rst	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/doc/source/lte-references.rst	Fri Sep 05 01:12:55 2014 +0200
@@ -159,3 +159,8 @@
    (Spain). 
 
 
+.. [ASHamza2013] Abdelbaset S. Hamza, Shady S. Khalifa, Haitham S. Hamza, and Khaled Elsayed, "A Survey on Inter-Cell Interference Coordination Techniques in OFDMA-based Cellular Networks", IEEE Communications Surveys & Tutorials, March 19, 2013
+
+.. [ZXie2009] Zheng Xie, Bernhard Walke, "Enhanced Fractional Frequency Reuse to Increase Capacity of OFDMA Systems", Proceedings of the 3rd international conference on New technologies, mobility and security, NTMS 2009
+
+.. [DKimura2012] D. Kimura, H. Seki, "Inter-Cell Interference Coordination (ICIC) Technology", FUJITSU Sci. Tech. J., Vol. 48, No. 1 (January 2012)
--- a/src/lte/doc/source/lte-testing.rst	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/doc/source/lte-testing.rst	Fri Sep 05 01:12:55 2014 +0200
@@ -142,7 +142,7 @@
 obtaining the tracing output produced by the scheduler after 4ms (this
 is needed to account for the initial delay in CQI reporting). The SINR
 which is calcualted by the simulator is also obtained using the
-``LteSinrChunkProcessor`` interface. The test
+``LteChunkProcessor`` interface. The test
 passes if both the following conditions are satisfied:
  
  #. the SINR calculated by the simulator correspond to the SNR
@@ -1419,3 +1419,139 @@
 
 The test case then verifies that the handover algorithm, when faced with more
 than one options of target cells, is able to choose the right one.
+
+Downlink Power Control
+----------------------
+
+The test suite ``lte-downlink-power-control`` checks correctness of Downlink 
+Power Control in three different ways: 
+
+ * LteDownlinkPowerControlSpectrumValue test case   check if 
+   ``LteSpectrumValueHelper::CreateTxPowerSpectralDensity`` is creating correct 
+   spectrum value for PSD for downlink transmission. The test vector contain EARFCN, 
+   system bandwidth, TX power, TX power for each RB, active RBs, and expected TxPSD. 
+   The test passes if TxPDS generated by 
+   ``LteSpectrumValueHelper::CreateTxPowerSpectralDensity`` is equal to expected TxPSD. 
+
+ * LteDownlinkPowerControlTestCase test case check if TX power difference between 
+   data and control channel is equal to configured PdschConfigDedicated::P_A value. 
+   TX power of control channel is measured by ``LteTestSinrChunkProcessor`` added 
+   to ``RsPowerChunkProcessor`` list in UE DownlinkSpectrumPhy. Tx power of data 
+   channel is measured in similar way, but it had to be implemented. Now 
+   ``LteTestSinrChunkProcessor`` is added to ``DataPowerChunkProcessor`` list in UE 
+   DownlinkSpectrumPhy. Test vector contain a set of all avaiable P_A values. Test 
+   pass if power diffrence equals P_A value. 
+
+ * LteDownlinkPowerControlRrcConnectionReconfiguration test case check if 
+   RrcConnectionReconfiguration is performed correctly. When FR entity gets UE 
+   measurements, it immediately calls function to change P_A value for this UE and also 
+   triggers callback connected with this event. Then, test check if UE gets 
+   RrcConnectionReconfiguration message (it trigger callback). Finally, it checks if eNB 
+   receive RrcConnectionReconfigurationCompleted message, what also trigger callback. 
+   The test passes if all event have occurred. The test is performed two times, with 
+   IdealRrcProtocol and with RealRrcProtocol.  
+
+
+Uplink Power Control Tests 
+--------------------------
+
+UE uses Uplink Power Control to automatically change Tx Power level for Uplink 
+Physical Channels. Tx Power is computed based on path-loss, number of RB used for transmission,
+some configurable parameters and TPC command from eNB.
+
+The test suite ``lte-uplink-power-control`` verifies if Tx Power is computed correctly.
+There are three different test cases: 
+
+ * LteUplinkOpenLoopPowerControlTestCase test case checks Uplink Power Control functionality 
+   in Open Loop mechanism. UE is attached to eNB and is transmitting data in Downlink and 
+   Uplink. Uplink Power Control with Open Loop mechanism is enabled and UE changes position 
+   each 100 ms. In each position Uplink Power Control entity is calculating new Tx Power level
+   for all uplink channels. These values are traced and test passes if Uplink Tx Power for 
+   PUSCH, PUCCH and SRS in each UE position are equal to expected values.
+
+ * LteUplinkClosedLoopPowerControlAbsoluteModeTestCase test case checks Uplink Power Control 
+   functionality with Closed Loop mechanism and Absolute Mode enabled. 
+   UE is attached to eNB and is transmitting data in Downlink and Uplink. Uplink Power Control 
+   with Closed Loop mechanism and Absolute Mode is enabled. UE is located 100 m from eNB and
+   is not changing its position. LteFfrSimple algorithm is used on eNB side to set TPC values in 
+   DL-DCI messages. TPC configuration in eNB is changed every 100 ms, so every 100 ms Uplink 
+   Power Control entity in UE should calculate different Tx Power level for all uplink channels. 
+   These values are traced and test passes if Uplink Tx Power for PUSCH, PUCCH and SRS
+   computed with all TCP values are equal to expected values.
+
+ * LteUplinkClosedLoopPowerControlAccumulatedModeTestCase test case checks Closed Loop Uplink
+   Power Control functionality with Closed Loop mechanism and Accumulative Mode enabled.
+   UE is attached to eNB and is transmitting data in Downlink and Uplink. Uplink Power Control 
+   with Closed Loop mechanism and Accumulative Mode is enabled. UE is located 100 m from eNB and
+   is not changing its position. As in above test case, LteFfrSimple algorithm is used on eNB 
+   side to set TPC values in DL-DCI messages, but in this case TPC command are set in DL-DCI 
+   only configured number of times, and after that TPC is set to be 1, what is mapped to value 
+   of 0 in Accumulative Mode (TS36.213 Table 5.1.1.1-2). TPC configuration in eNB is changed 
+   every 100 ms. UE is accumulating these values and calculates Tx Power levels for all uplink 
+   channels based on accumulated value. If computed Tx Power level is lower than minimal 
+   UE Tx Power, UE should transmit with its minimal Tx Power. If computed Tx Power level is
+   higher than maximal UE Tx Power, UE should transmit with its maximal Tx Power.    
+   Tx Power levels for PUSCH, PUCCH and SRS are traced and test passes if they are equal to 
+   expected values.
+
+
+Frequency Reuse Algorithms
+--------------------------
+
+The test suite ``lte-frequency-reuse`` contain two types of test cases. 
+
+First type of test cases check if RBGs are used correctly according to FR algorithm 
+policy. We are testing if scheduler use only RBGs allowed by FR configuration. To 
+check which RBGs are used ``LteSimpleSpectrumPhy`` is attached to Downlink Channel. 
+It notifies when data downlink channel transmission has occured and pass signal 
+TxPsd spectrum value to check which RBs were used for transmission. The test vector 
+comprise a set of configuration for Hard and Strict FR algorithms (there is no point 
+to check other FR algorithms in this way because they use entire cell bandwidth). 
+Test passes if none of not allowed RBGs are used. 
+
+Second type of test cases check if UE is served within proper sub-band and with proper 
+transmission power. In this test scenario, there are two eNBs.There are also two UEs 
+and each eNB is serving one.  One uses Frequency Reuse algorithm and second one does not. 
+Second eNB is responsible for generating interferences in whole system bandwidth. 
+UE served by first eNB is changing position each few second (rather slow because time is
+needed to report new UE Measurements). To check which RBGs are used for this UE
+``LteSimpleSpectrumPhy`` is attached to Downlink Channel. It notifies when data 
+downlink channel transmission in cell 1 has occured and pass signal TxPsd spectrum value 
+to check which RBs were used for transmission and their power level. 
+The same approach is applied in Uplink direction and second ``LteSimpleSpectrumPhy``
+is attached to Uplink Channel. Test passes if UE served by eNB with FR algorithm 
+is served in DL and UL with expected RBs and with expected power level. 
+Test vector comprise a configuration for Strict FR, Soft FR, Soft FFR, Enchanced FFR.
+Each FR algorithm is tested with all schedulers, which support FR (i.e. PF, PSS, CQA, 
+TD-TBFQ, FD-TBFQ). (Hard FR do not use UE measurements, so there is no point to perform 
+this type of test for Hard FR).
+
+Test case for Distributed FFR algorithm is quite similar to above one, but since eNBs need 
+to exchange some information, scenario with EPC enabled and X2 interfaces is considered.
+Moreover, both eNB are using Distributed FFR algorithm. There are 2 UE in first cell, 
+and 1 in second cell. Position of each UE is changed (rather slow because time is
+needed to report new UE Measurements), to obtain different result from calculation in 
+Distributed FFR algorithm entities. To check which RBGs are used for UE transmission
+``LteSimpleSpectrumPhy`` is attached to Downlink Channel. It notifies when data 
+downlink channel transmission has occured and pass signal TxPsd spectrum value 
+to check which RBs were used for transmission and their power level. 
+The same approach is applied in Uplink direction and second ``LteSimpleSpectrumPhy``
+is attached to Uplink Channel. 
+Test passes if UE served by eNB in cell 2, is served in DL and UL with expected RBs 
+and with expected power level. Test vector compirse a configuration for Distributed FFR.
+Test is performed with all schedulers, which support FR (i.e. PF, PSS, CQA, 
+TD-TBFQ, FD-TBFQ).
+
+
+Inter-cell Interference with FR algorithms Tests 
+-------------------------------------------------
+
+The test suite ``lte-interference-fr`` is very similar to ``lte-interference``. 
+Topology (Figure :ref:`fig-lte-interference-test-scenario`) is the same and test checks 
+interference level. The difference is that, in this test case Frequency Reuse algorithms 
+are enabled and we are checking interference level on different RBGs (not only on one). 
+For example, when we install Hard FR algorithm in eNbs, and first half of system bandwidth 
+is assigned to one eNb, and second half to second eNb, interference level should be much 
+lower compared to legacy scenario. The test vector comprise a set of configuration for 
+all available Frequency Reuse Algorithms. Test passes if calculated SINR on specific 
+RBs is equal to these obtained by Octave script.
--- a/src/lte/doc/source/lte-user.rst	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/doc/source/lte-user.rst	Fri Sep 05 01:12:55 2014 +0200
@@ -665,7 +665,10 @@
 By using the class ``RadioEnvironmentMapHelper`` it is possible to output
 to a file a Radio Environment Map (REM), i.e., a uniform 2D grid of values
 that represent the Signal-to-noise ratio in the downlink with respect
-to the eNB that has the strongest signal at each point. 
+to the eNB that has the strongest signal at each point. It is possible
+to specify if REM should be generated for data or control channel. Also user
+can set the RbId, for which REM will be generated. Default RbId is -1, what
+means that REM will generated with averaged Signal-to-noise ratio from all RBs.
 
 To do this, you just need to add the following code to your simulation
 program towards the end, right before the call to Simulator::Run ()::
@@ -680,6 +683,8 @@
   remHelper->SetAttribute ("YMax", DoubleValue (300.0));
   remHelper->SetAttribute ("YRes", UintegerValue (75));
   remHelper->SetAttribute ("Z", DoubleValue (0.0));
+  remHelper->SetAttribute ("UseDataChannel", BooleanValue (true));
+  remHelper->SetAttribute ("RbId", IntegerValue (10));
   remHelper->Install ();
 
 By configuring the attributes of the ``RadioEnvironmentMapHelper`` object
@@ -1501,7 +1506,404 @@
     NS_LOG=LteEnbRrc:LteUeRrc:EpcX2 ./waf --run lena-x2-handover
 
 
-
+Frequency Reuse Algorithms
+--------------------------
+
+In this section we will describe how to use Frequency Reuse Algorithms 
+in eNb within LTE simulations. 
+There are two possible ways of configuration. The first approach is the 
+"manual" one, it requires more parameters to be configured, but allow user 
+to configure FR algorithm as he/she needs. The second approach is more 
+"automatic". It is very convenient, because is the same for each FR algorithm, 
+so user can switch FR algorithm very quickly by changing only type of FR 
+algorithm. One drawback is that "automatic" approach uses only limited set 
+of configurations for each algorithm, what make it less flexible, but is 
+sufficient for most of cases.
+
+These two approaches will be described more in following sub-section.
+
+If user do not configure Frequency Reuse algorithm, default one 
+(i.e. LteFrNoOpAlgorithm) is installed in eNb. It acts as if FR 
+algorithm was disabled.
+
+One thing that should be mentioned is that most of implemented FR algorithms work with
+cell bandwidth greater or equal than 15 RBs. This limitation is caused by requirement
+that at least three continuous RBs have to be assigned to UE for transmission.
+
+Manual configuration
+********************
+
+Frequency reuse algorithm can be configured "manually" within the simulation 
+program by setting type of FR algorithm and all its attributes. Currently, 
+seven FR algorithms are implemented:
+
+ - ``ns3::LteFrNoOpAlgorithm``
+ - ``ns3::LteFrHardAlgorithm``
+ - ``ns3::LteFrStrictAlgorithm``
+ - ``ns3::LteFrSoftAlgorithm``
+ - ``ns3::LteFfrSoftAlgorithm``
+ - ``ns3::LteFfrEnhancedAlgorithm``
+ - ``ns3::LteFfrDistributedAlgorithm``
+
+
+Selecting a FR algorithm is done via the ``LteHelper`` object and 
+its ``SetFfrAlgorithmType`` method as shown below::
+
+   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+   lteHelper->SetFfrAlgorithmType ("ns3::LteFrHardAlgorithm");
+
+Each implemented FR algorithm provide several configurable attributes. Users do 
+not have to care about UL and DL bandwidth configuration, because it is done 
+automatically during cell configuration. To change bandwidth for FR algorithm,
+configure required values for ``LteEnbNetDevice``::
+
+   uint8_t bandwidth = 100;
+   lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
+   lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
+
+
+Now, each FR algorithms configuration will be described. 
+
+Hard Frequency Reuse Algorithm
+++++++++++++++++++++++++++++++
+
+As described in Section :ref:`sec-fr-hard-algorithm` of the Design Documentation 
+``ns3::LteFrHardAlgorithm`` uses one sub-band. To configure this sub-band user need 
+to specify offset and bandwidth for DL and UL in number of RBs. 
+
+Hard Frequency Reuse Algorithm provides following attributes:
+
+ * ``DlSubBandOffset``: Downlink Offset in number of Resource Block Groups
+ * ``DlSubBandwidth``: Downlink Transmission SubBandwidth Configuration in number of Resource Block Groups
+ * ``UlSubBandOffset``: Uplink Offset in number of Resource Block Groups
+ * ``UlSubBandwidth``: Uplink Transmission SubBandwidth Configuration in number of Resource Block Groups
+
+Example configuration of LteFrHardAlgorithm can be done in following way::
+
+   lteHelper->SetFfrAlgorithmType ("ns3::LteFrHardAlgorithm");
+   lteHelper->SetFfrAlgorithmAttribute ("DlSubBandOffset", UintegerValue (8));
+   lteHelper->SetFfrAlgorithmAttribute ("DlSubBandwidth", UintegerValue (8));
+   lteHelper->SetFfrAlgorithmAttribute ("UlSubBandOffset", UintegerValue (8));
+   lteHelper->SetFfrAlgorithmAttribute ("UlSubBandwidth", UintegerValue (8));
+   NetDeviceContainer enbDevs = lteHelper->InstallEnbDevice (enbNodes.Get(0));
+
+Above example allow eNB to use only RBs from 8 to 16 in DL and UL, while entire cell
+bandwidth is 25. 
+
+
+Strict Frequency Reuse Algorithm
+++++++++++++++++++++++++++++++++
+
+Strict Frequency Reuse Algorithm uses two sub-bands: one common for each cell and one 
+private. There is also RSRQ threshold, which is needed to decide within which sub-band 
+UE should be served. Moreover the power transmission in these sub-bands can be different. 
+
+Strict Frequency Reuse Algorithm provides following attributes:
+
+ * ``UlCommonSubBandwidth``: Uplink Common SubBandwidth Configuration in number of Resource Block Groups
+ * ``UlEdgeSubBandOffset``: Uplink Edge SubBand Offset in number of Resource Block Groups
+ * ``UlEdgeSubBandwidth``: Uplink Edge SubBandwidth Configuration in number of Resource Block Groups
+ * ``DlCommonSubBandwidth``: Downlink Common SubBandwidth Configuration in number of Resource Block Groups
+ * ``DlEdgeSubBandOffset``: Downlink Edge SubBand Offset in number of Resource Block Groups
+ * ``DlEdgeSubBandwidth``: Downlink Edge SubBandwidth Configuration in number of Resource Block Groups
+ * ``RsrqThreshold``: If the RSRQ of is worse than this threshold, UE should be served in edge sub-band
+ * ``CenterPowerOffset``: PdschConfigDedicated::Pa value for center sub-band, default value dB0
+ * ``EdgePowerOffset``: PdschConfigDedicated::Pa value for edge sub-band, default value dB0
+ * ``CenterAreaTpc``: TPC value which will be set in DL-DCI for UEs in center area, 
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+ * ``EdgeAreaTpc``: TPC value which will be set in DL-DCI for UEs in edge area,
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+
+
+Example below allow eNB to use RBs from 0 to 6 as common sub-band and from 12 to 18 as 
+private sub-band in DL and UL, RSRQ threshold is 20 dB, power in center area equals 
+``LteEnbPhy::TxPower - 3dB``, power in edge area equals ``LteEnbPhy::TxPower + 3dB``::
+
+   lteHelper->SetFfrAlgorithmType ("ns3::LteFrStrictAlgorithm");
+   lteHelper->SetFfrAlgorithmAttribute ("DlCommonSubBandwidth", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("UlCommonSubBandwidth", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandOffset", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandwidth", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (20));
+   lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+			 UintegerValue (LteRrcSap::PdschConfigDedicated::dB_3));
+   lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+			 UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+   lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (1));
+   lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (2));
+   NetDeviceContainer enbDevs = lteHelper->InstallEnbDevice (enbNodes.Get(0));
+
+
+Soft Frequency Reuse Algorithm
+++++++++++++++++++++++++++++++
+
+With Soft Frequency Reuse Algorithm, eNb uses entire cell bandwidth, but there are two 
+sub-bands, within UEs are served with different power level. 
+
+Soft Frequency Reuse Algorithm provides following attributes:
+
+ * ``UlEdgeSubBandOffset``: Uplink Edge SubBand Offset in number of Resource Block Groups
+ * ``UlEdgeSubBandwidth``: Uplink Edge SubBandwidth Configuration in number of Resource Block Groups
+ * ``DlEdgeSubBandOffset``: Downlink Edge SubBand Offset in number of Resource Block Groups
+ * ``DlEdgeSubBandwidth``: Downlink Edge SubBandwidth Configuration in number of Resource Block Groups
+ * ``AllowCenterUeUseEdgeSubBand``: If true center UEs can receive on edge sub-band RBGs, otherwise 
+   edge sub-band is allowed only for edge UEs, default value is true
+ * ``RsrqThreshold``: If the RSRQ of is worse than this threshold, UE should be served in edge sub-band
+ * ``CenterPowerOffset``: PdschConfigDedicated::Pa value for center sub-band, default value dB0
+ * ``EdgePowerOffset``: PdschConfigDedicated::Pa value for edge sub-band, default value dB0
+ * ``CenterAreaTpc``: TPC value which will be set in DL-DCI for UEs in center area, 
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+ * ``EdgeAreaTpc``: TPC value which will be set in DL-DCI for UEs in edge area,
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+
+Example below configures RBs from 8 to 16 to be used by cell edge UEs and this sub-band 
+is not available for cell center users. RSRQ threshold is 20 dB, power in center area
+equals ``LteEnbPhy::TxPower``, power in edge area equals ``LteEnbPhy::TxPower + 3dB``::
+
+   lteHelper->SetFfrAlgorithmType ("ns3::LteFrSoftAlgorithm");
+   lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (8));
+   lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (8));
+   lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandOffset", UintegerValue (8));
+   lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandwidth", UintegerValue (8));
+   lteHelper->SetFfrAlgorithmAttribute ("AllowCenterUeUseEdgeSubBand", BooleanValue (false));
+   lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (20));
+   lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+			 UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+   lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+		         UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+   NetDeviceContainer enbDevs = lteHelper->InstallEnbDevice (enbNodes.Get(0));
+
+
+Soft Fractional Frequency Reuse Algorithm
++++++++++++++++++++++++++++++++++++++++++
+
+Soft Fractional Frequency Reuse (SFFR) uses three sub-bands: center, medium (common)
+and edge. User have to configure only two of them: common and edge. Center sub-band
+will be composed from the remaining bandwidth. Each sub-band can be served with
+different transmission power. Since there are three sub-bands, two RSRQ thresholds needs to
+be configured.
+
+
+Soft Fractional Frequency Reuse Algorithm provides following attributes:
+
+ * ``UlCommonSubBandwidth``: Uplink Common SubBandwidth Configuration in number of Resource Block Groups
+ * ``UlEdgeSubBandOffset``: Uplink Edge SubBand Offset in number of Resource Block Groups
+ * ``UlEdgeSubBandwidth``: Uplink Edge SubBandwidth Configuration in number of Resource Block Groups
+ * ``DlCommonSubBandwidth``: Downlink Common SubBandwidth Configuration in number of Resource Block Groups
+ * ``DlEdgeSubBandOffset``: Downlink Edge SubBand Offset in number of Resource Block Groups
+ * ``DlEdgeSubBandwidth``: Downlink Edge SubBandwidth Configuration in number of Resource Block Groups
+ * ``CenterRsrqThreshold``: If the RSRQ of is worse than this threshold, UE should be served in medium sub-band
+ * ``EdgeRsrqThreshold``: If the RSRQ of is worse than this threshold, UE should be served in edge sub-band
+ * ``CenterAreaPowerOffset``: PdschConfigDedicated::Pa value for center sub-band, default value dB0
+ * ``MediumAreaPowerOffset``: PdschConfigDedicated::Pa value for medium sub-band, default value dB0
+ * ``EdgeAreaPowerOffset``: PdschConfigDedicated::Pa value for edge sub-band, default value dB0
+ * ``CenterAreaTpc``: TPC value which will be set in DL-DCI for UEs in center area, 
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+ * ``MediumAreaTpc``: TPC value which will be set in DL-DCI for UEs in medium area, 
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+ * ``EdgeAreaTpc``: TPC value which will be set in DL-DCI for UEs in edge area,
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+
+
+In example below RBs from 0 to 6 will be used as common (medium) sub-band,
+RBs from 6 to 12 will be used as edge sub-band and RBs from 12 to 24 will be used as
+center sub-band (it is composed with remaining RBs). RSRQ threshold between center 
+and medium area is 28 dB, RSRQ threshold between medium and edge area is 18 dB.
+Power in center area equals ``LteEnbPhy::TxPower - 3dB``, power in medium area equals 
+``LteEnbPhy::TxPower + 3dB``, power in edge area equals ``LteEnbPhy::TxPower + 3dB``::
+
+   lteHelper->SetFfrAlgorithmType ("ns3::LteFfrSoftAlgorithm");
+   lteHelper->SetFfrAlgorithmAttribute ("UlCommonSubBandwidth", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("DlCommonSubBandwidth", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (0));
+   lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandOffset", UintegerValue (0));
+   lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandwidth", UintegerValue (6));
+   lteHelper->SetFfrAlgorithmAttribute ("CenterRsrqThreshold", UintegerValue (28));
+   lteHelper->SetFfrAlgorithmAttribute ("EdgeRsrqThreshold", UintegerValue (18));
+   lteHelper->SetFfrAlgorithmAttribute ("CenterAreaPowerOffset",
+			 UintegerValue (LteRrcSap::PdschConfigDedicated::dB_3));
+   lteHelper->SetFfrAlgorithmAttribute ("MediumAreaPowerOffset",
+			 UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+   lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaPowerOffset",
+			 UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+   NetDeviceContainer enbDevs = lteHelper->InstallEnbDevice (enbNodes.Get(0));
+
+
+Enhanced Fractional Frequency Reuse Algorithm
++++++++++++++++++++++++++++++++++++++++++++++
+
+Enhanced Fractional Frequency Reuse (EFFR) reserve part of system bandwidth for each cell
+(typically there are 3 cell types and each one gets 1/3 of system bandwidth). Then part of
+this subbandwidth it used as `Primary Segment` with reuse factor 3 and as `Secondary Segment`
+with reuse factor 1. User has to configure (for DL and UL) offset of the cell subbandwidth 
+in number of RB, number of RB which will be used as `Primary Segment` and number of RB which 
+will be used as `Secondary Segment`. `Primary Segment` is used by cell at will, but RBs from 
+`Secondary Segment` can be assigned to UE only is CQI feedback from this UE have higher value 
+than configured CQI threshold. UE is considered as edge UE when its RSRQ is lower than ``RsrqThreshold``.
+
+Since each eNb needs to know where are Primary and Secondary of other cell types, 
+it will calculate them assuming configuration is the same for each cell and only subbandwidth offsets
+are different. So it is important to divide available system bandwidth equally to each cell and apply 
+the same configuration of Primary and Secondary Segments to them. 
+
+
+Enhanced Fractional Frequency Reuse Algorithm provides following attributes:
+
+ * ``UlSubBandOffset``: Uplink SubBand Offset for this cell in number of Resource Block Groups
+ * ``UlReuse3SubBandwidth``: Uplink Reuse 3 SubBandwidth Configuration in number of Resource Block Groups
+ * ``UlReuse1SubBandwidth``: Uplink Reuse 1 SubBandwidth Configuration in number of Resource Block Groups
+ * ``DlSubBandOffset``: Downlink SubBand Offset for this cell in number of Resource Block Groups
+ * ``DlReuse3SubBandwidth``: Downlink Reuse 3 SubBandwidth Configuration in number of Resource Block Groups
+ * ``DlReuse1SubBandwidth``: Downlink Reuse 1 SubBandwidth Configuration in number of Resource Block Groups
+ * ``RsrqThreshold``: If the RSRQ of is worse than this threshold, UE should be served in edge sub-band
+ * ``CenterAreaPowerOffset``: PdschConfigDedicated::Pa value for center sub-band, default value dB0
+ * ``EdgeAreaPowerOffset``: PdschConfigDedicated::Pa value for edge sub-band, default value dB0
+ * ``DlCqiThreshold``: If the DL-CQI for RBG of is higher than this threshold, transmission on RBG is possible
+ * ``UlCqiThreshold``: If the UL-CQI for RBG of is higher than this threshold, transmission on RBG is possible
+ * ``CenterAreaTpc``: TPC value which will be set in DL-DCI for UEs in center area, 
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+ * ``EdgeAreaTpc``: TPC value which will be set in DL-DCI for UEs in edge area,
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+
+
+In example below offset in DL and UL is 0 RB, 4 RB will be used in `Primary Segment` and 
+`Secondary Segment`. RSRQ threshold between center and edge area is 25 dB. DL and UL CQI 
+thresholds are set to value of 10. Power in center area equals ``LteEnbPhy::TxPower - 6dB``, 
+power in edge area equals ``LteEnbPhy::TxPower + 0dB``::
+
+   lteHelper->SetFfrAlgorithmType("ns3::LteFfrEnhancedAlgorithm");
+   lteHelper->SetFfrAlgorithmAttribute("RsrqThreshold", UintegerValue (25));
+   lteHelper->SetFfrAlgorithmAttribute("DlCqiThreshold", UintegerValue (10));
+   lteHelper->SetFfrAlgorithmAttribute("UlCqiThreshold", UintegerValue (10));
+   lteHelper->SetFfrAlgorithmAttribute("CenterAreaPowerOffset",
+		  UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
+   lteHelper->SetFfrAlgorithmAttribute("EdgeAreaPowerOffset",
+		  UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+   lteHelper->SetFfrAlgorithmAttribute("UlSubBandOffset", UintegerValue (0));
+   lteHelper->SetFfrAlgorithmAttribute("UlReuse3SubBandwidth", UintegerValue (4));
+   lteHelper->SetFfrAlgorithmAttribute("UlReuse1SubBandwidth", UintegerValue (4));
+   lteHelper->SetFfrAlgorithmAttribute("DlSubBandOffset", UintegerValue (0));
+   lteHelper->SetFfrAlgorithmAttribute("DlReuse3SubBandwidth", UintegerValue (4));
+   lteHelper->SetFfrAlgorithmAttribute("DlReuse1SubBandwidth", UintegerValue (4));
+
+
+Distributed Fractional Frequency Reuse Algorithm
+++++++++++++++++++++++++++++++++++++++++++++++++
+
+Distributed Fractional Frequency Reuse requires X2 interface between all eNB to be installed. 
+X2 interfaces can be installed only when EPC is configured, so this FFR scheme can be used only with
+EPC scenarios. 
+
+With Distributed Fractional Frequency Reuse  Algorithm, eNb uses entire cell bandwidth and there can 
+be two sub-bands: center sub-band and edge sub-band . Within these sub-bands UEs can be served with 
+different power level. Algorithm adaptively selects RBs for cell-edge sub-band on basis of 
+coordination information (i.e. RNTP) from adjecent cells and notifies the base stations of the adjacent cells, 
+which RBs it selected to use in edge sub-band. If there are no UE classified as edge UE in cell, 
+eNB will not use any RBs as edge sub-band.
+
+Distributed Fractional Frequency Reuse Algorithm provides following attributes:
+
+ * ``CalculationInterval``: Time interval between calculation of Edge sub-band, Default value 1 second
+ * ``RsrqThreshold``: If the RSRQ of is worse than this threshold, UE should be served in edge sub-band
+ * ``RsrpDifferenceThreshold``: If the difference between the power of the signal received by UE from
+   the serving cell and the power of the signal received from the adjacent cell is less than a 
+   RsrpDifferenceThreshold value, the cell weight is incremented
+ * ``CenterPowerOffset``: PdschConfigDedicated::Pa value for edge sub-band, default value dB0
+ * ``EdgePowerOffset``: PdschConfigDedicated::Pa value for edge sub-band, default value dB0
+ * ``EdgeRbNum``: Number of RB that can be used in edge sub-band
+ * ``CenterAreaTpc``: TPC value which will be set in DL-DCI for UEs in center area, 
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+ * ``EdgeAreaTpc``: TPC value which will be set in DL-DCI for UEs in edge area,
+   Absolute mode is used, default value 1 is mapped to -1 according to TS36.213 Table 5.1.1.1-2
+
+In example below calculation interval is 500 ms. RSRQ threshold between center and edge area is 25. 
+RSRP Difference Threshold is set to be 5. In DL and UL 6 RB will be used by each cell in edge sub-band.  
+Power in center area equals ``LteEnbPhy::TxPower - 0dB``, power in edge area equals ``LteEnbPhy::TxPower + 3dB``::
+
+  lteHelper->SetFfrAlgorithmType("ns3::LteFfrDistributedAlgorithm");
+  lteHelper->SetFfrAlgorithmAttribute("CalculationInterval", TimeValue(MilliSeconds(500)));
+  lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
+  lteHelper->SetFfrAlgorithmAttribute ("RsrpDifferenceThreshold", UintegerValue (5));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgeRbNum", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+		  UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+		  UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+
+
+Automatic configuration
+***********************
+
+Frequency Reuse algorithms can also be configured in more “automatic” way by setting 
+only the bandwidth and FrCellTypeId. During initialization of FR instance, configuration 
+for set bandwidth and FrCellTypeId will be taken from configuration table. It is important 
+that only sub-bands will be configured, thresholds and transmission power will be set 
+to default values. If one wants, he/she can change thresholds and transmission power 
+as show in previous sub-section. 
+
+There are three FrCellTypeId : ``1, 2, 3``, which correspond to three different 
+configurations for each bandwidth. Three configurations allow to have different 
+configurations in neighbouring cells in hexagonal eNB layout. If user needs to have
+more different configuration for neighbouring cells, he/she need to use manual 
+configuration.
+
+Example below show automatic FR algorithm configuration::
+
+   lteHelper->SetFfrAlgorithmType("ns3::LteFfrSoftAlgorithm");
+   lteHelper->SetFfrAlgorithmAttribute("FrCellTypeId", UintegerValue (1));
+   NetDeviceContainer enbDevs = lteHelper->InstallEnbDevice (enbNodes.Get(0));
+
+
+Uplink Power Control
+--------------------
+
+Uplink Power Control functionality is enabled by default. User can disable it by setting 
+the boolean attribute ``ns3::LteUePhy::EnableUplinkPowerControl`` to true.
+
+User can switch between Open Loop Power Control and Closed Loop Power Control mechanisms
+by setting the boolean attribute ``ns3::LteUePowerControl::ClosedLoop``. 
+By default Closed Loop Power Control with Accumulation Mode is enabled.
+
+Path-loss is key component of Uplink Power Control. It is computed as difference between 
+filtered RSRP and ReferenceSignalPower parameter. ReferenceSignalPower is 
+sent with SIB2.
+
+Attributes available in Uplink Power Control:
+
+ * ``ClosedLoop``: if true Closed Loop Uplink Power Control mode is enabled and Open Loop 
+   Power Control otherwise, default value is false
+ * ``AccumulationEnabled``: if true Accumulation Mode is enabled and Absolute mode otherwise, 
+   default value is false 
+ * ``Alpha``: the path loss compensation factor, default value is 1.0
+ * ``Pcmin``: minimal UE TxPower, default value is -40 dBm
+ * ``Pcmax``: maximal UE TxPower, default value is 23 dBm
+ * ``PoNominalPusch``: this parameter should be set by higher layers, but currently 
+   it needs to be configured by attribute system, possible values are 
+   integers in range (-126 ... 24), Default value is -80
+ * ``PoUePusch``: this parameter should be set by higher layers, but currently 
+   it needs to be configured by attribute system, possible values are 
+   integers in range (-8 ... 7), Default value is 0
+ * ``PsrsOffset``: this parameter should be set by higher layers, but currently 
+   it needs to be configured by attribute system, possible values are 
+   integers in range (0 ... 15), Default value is 7, what gives P_Srs_Offset_Value = 0
+
+Traced values in Uplink Power Control:
+ * ``ReportPuschTxPower``: Current UE TxPower for PUSCH
+ * ``ReportPucchTxPower``: Current UE TxPower for PUCCH
+ * ``ReportSrsTxPower``: Current UE TxPower for SRS
+
+
+Example configuration is presented below::
+
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (30));
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (true));
+
+As an example, user can take a look and run the lena-uplink-power-control program.
 
 
 Examples Programs
@@ -1511,7 +1913,6 @@
 show how to simulate different LTE scenarios. 
 
 
-
 Reference scenarios
 -------------------
 
@@ -1819,3 +2220,123 @@
 between the two handover algorithms in this campaign scenario. It would be
 interesting to see their performance in different scenarios, such as scenarios
 with home eNodeBs deployment.
+
+
+Frequency Reuse examples
+**********************************
+
+There are two examples showing Frequency Reuse Algorithms functionality.
+
+``lena-frequency-reuse`` is simple example with 3 eNBs in triangle layout. 
+There are 3 cell edge UEs, which are located in the center of this triangle and 
+3 cell center UEs (one near each eNB). User can also specify the number of randomly 
+located UEs. FR algorithm is installed in eNBs and each eNB has different FrCellTypeId, 
+what means each eNB uses different FR configuration. User can run ``lena-frequency-reuse`` 
+with 6 different FR algorithms: NoOp, Hard FR, Strict FR, Soft FR, Soft FFR and Enhanced FFR.
+To run scenario with Distributed FFR algorithm, user should use ``lena-distributed-ffr``. 
+These two examples are very similar, but they were splitted because Distributed FFR requires 
+EPC to be used, and other algorihtms do not. 
+
+To run ``lena-frequency-reuse`` with different Frequency Reuse algorithms, user needs to specify 
+FR algorithm by overriding the default attribute ``ns3::LteHelper::FfrAlgorithm``.
+Example command to run ``lena-frequency-reuse`` with Soft FR algorithm is presented below::
+
+   $ ./waf --run "lena-frequency-reuse --ns3::LteHelper::FfrAlgorithm=ns3::LteFrSoftAlgorithm"
+
+In these examples functionality to generate REM and spectrum analyzer trace was added. 
+User can enable generation of it by setting ``generateRem`` and ``generateSpectrumTrace``
+attributes. 
+
+Command to generate REM for RB 1 in data channel from ``lena-frequency-reuse`` scenario 
+with Soft FR algorithm is presented below::
+
+   $ ./waf --run "lena-frequency-reuse --ns3::LteHelper::FfrAlgorithm=ns3::LteFrSoftAlgorithm
+     --generateRem=true --remRbId=1"
+
+Radio Environment Map for Soft FR is presented in Figure :ref:`fig-lte-soft-fr-1-rem`.
+
+.. _fig-lte-soft-fr-1-rem:
+
+.. figure:: figures/lte-fr-soft-1-rem.*
+   :align: center
+
+   REM for RB 1 obtained from ``lena-frequency-reuse`` example with Soft FR 
+   algorithm enabled
+
+
+Command to generate spectrum trace from ``lena-frequency-reuse`` scenario 
+with Soft FFR algorithm is presented below (Spectrum Analyzer position needs to be configured 
+inside script)::
+
+   $ ./waf --run "lena-frequency-reuse --ns3::LteHelper::FfrAlgorithm=ns3::LteFfrSoftAlgorithm
+     --generateSpectrumTrace=true"
+
+Example spectrum analyzer trace is presented in figure :ref:`fig-lte-soft-ffr-2-spectrum-trace`.
+As can be seen, different data channel subbands are sent with different power level
+(according to configuration), while control channel is transmitted with uniform power 
+along entire system bandwidth.
+
+
+.. _fig-lte-soft-ffr-2-spectrum-trace:
+
+.. figure:: figures/lte-ffr-soft-2-spectrum-trace.*
+   :align: center
+
+   Spectrum Analyzer trace obtained from ``lena-frequency-reuse`` example 
+   with Soft FFR algorithm enabled. Spectrum Analyzer was located need eNB 
+   with FrCellTypeId 2.
+
+
+``lena-dual-stripe`` can be also run with Frequency Reuse algorithms installed in all macro eNB. 
+User needs to specify FR algorithm by overriding the default attribute ``ns3::LteHelper::FfrAlgorithm``.
+Example command to run ``lena-dual-stripe`` with Hard FR algorithm is presented below::
+
+   $ ./waf --run="lena-dual-stripe
+     --simTime=50 --nBlocks=0 --nMacroEnbSites=7 --nMacroEnbSitesX=2
+     --epc=1 --useUdp=0 --outdoorUeMinSpeed=16.6667 --outdoorUeMaxSpeed=16.6667
+     --ns3::LteHelper::HandoverAlgorithm=ns3::NoOpHandoverAlgorithm
+     --ns3::LteHelper::FfrAlgorithm=ns3::LteFrHardAlgorithm
+     --ns3::RadioBearerStatsCalculator::DlRlcOutputFilename=no-op-DlRlcStats.txt
+     --ns3::RadioBearerStatsCalculator::UlRlcOutputFilename=no-op-UlRlcStats.txt
+     --ns3::PhyStatsCalculator::DlRsrpSinrFilename=no-op-DlRsrpSinrStats.txt
+     --ns3::PhyStatsCalculator::UlSinrFilename=no-op-UlSinrStats.txt
+     --RngRun=1" > no-op.txt
+
+Example command to generate REM for RB 1 in data channel from ``lena-dual-stripe`` scenario 
+with Hard FR algorithm is presented below::
+
+   $ ./waf --run="lena-dual-stripe
+     --simTime=50 --nBlocks=0 --nMacroEnbSites=7 --nMacroEnbSitesX=2
+     --epc=0 --useUdp=0 --outdoorUeMinSpeed=16.6667 --outdoorUeMaxSpeed=16.6667
+     --ns3::LteHelper::HandoverAlgorithm=ns3::NoOpHandoverAlgorithm
+     --ns3::LteHelper::FfrAlgorithm=ns3::LteFrHardAlgorithm
+     --ns3::RadioBearerStatsCalculator::DlRlcOutputFilename=no-op-DlRlcStats.txt
+     --ns3::RadioBearerStatsCalculator::UlRlcOutputFilename=no-op-UlRlcStats.txt
+     --ns3::PhyStatsCalculator::DlRsrpSinrFilename=no-op-DlRsrpSinrStats.txt
+     --ns3::PhyStatsCalculator::UlSinrFilename=no-op-UlSinrStats.txt
+     --RngRun=1 --generateRem=true --remRbId=1" > no-op.txt
+
+Radio Environment Maps for RB 1, 10 and 20 generated from ``lena-dual-stripe``
+scenario with Hard Frequency Reuse algorithm are presented in the figures 
+below. These RB were selected because each one is used by different FR cell type.
+
+.. _fig-lte-hard-fr-1-rem:
+
+.. figure:: figures/lte-fr-hard-1-rem.*
+   :align: center
+
+   REM for RB 1 obtained from ``lena-dual-stripe`` simulation with Hard FR algorithm enabled
+
+.. _fig-lte-hard-fr-2-rem:
+
+.. figure:: figures/lte-fr-hard-2-rem.*
+   :align: center
+
+   REM for RB 10 obtained from ``lena-dual-stripe`` simulation with Hard FR algorithm enabled
+
+.. _fig-lte-hard-fr-3-rem:
+
+.. figure:: figures/lte-fr-hard-3-rem.*
+   :align: center
+
+   REM for RB 20 obtained from ``lena-dual-stripe`` simulation with Hard FR algorithm enabled
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/examples/lena-distributed-ffr.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,393 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/lte-module.h"
+#include "ns3/spectrum-module.h"
+#include "ns3/config-store.h"
+#include <ns3/buildings-helper.h>
+#include "ns3/point-to-point-epc-helper.h"
+#include "ns3/internet-module.h"
+#include "ns3/point-to-point-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/log.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("LenaDistributedFrequencyReuse");
+
+void
+PrintGnuplottableUeListToFile (std::string filename)
+{
+  std::ofstream outFile;
+  outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
+  if (!outFile.is_open ())
+    {
+      NS_LOG_ERROR ("Can't open file " << filename);
+      return;
+    }
+  for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
+    {
+      Ptr<Node> node = *it;
+      int nDevs = node->GetNDevices ();
+      for (int j = 0; j < nDevs; j++)
+        {
+          Ptr<LteUeNetDevice> uedev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
+          if (uedev)
+            {
+              Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
+              outFile << "set label \"" << uedev->GetImsi ()
+                      << "\" at " << pos.x << "," << pos.y << " left font \"Helvetica,4\" textcolor rgb \"grey\" front point pt 1 ps 0.3 lc rgb \"grey\" offset 0,0"
+                      << std::endl;
+            }
+        }
+    }
+}
+
+void
+PrintGnuplottableEnbListToFile (std::string filename)
+{
+  std::ofstream outFile;
+  outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
+  if (!outFile.is_open ())
+    {
+      NS_LOG_ERROR ("Can't open file " << filename);
+      return;
+    }
+  for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
+    {
+      Ptr<Node> node = *it;
+      int nDevs = node->GetNDevices ();
+      for (int j = 0; j < nDevs; j++)
+        {
+          Ptr<LteEnbNetDevice> enbdev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
+          if (enbdev)
+            {
+              Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
+              outFile << "set label \"" << enbdev->GetCellId ()
+                      << "\" at " << pos.x << "," << pos.y
+                      << " left font \"Helvetica,4\" textcolor rgb \"white\" front  point pt 2 ps 0.3 lc rgb \"white\" offset 0,0"
+                      << std::endl;
+            }
+        }
+    }
+}
+
+int main (int argc, char *argv[])
+{
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (true));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (true));
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  Config::SetDefault ("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue (true));
+
+  //Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+  uint32_t runId = 3;
+  uint16_t numberOfRandomUes = 0;
+  double simTime = 5.000;
+  bool generateSpectrumTrace = false;
+  bool generateRem = false;
+  int32_t remRbId = -1;
+  uint8_t bandwidth = 25;
+  double distance = 1000;
+  Box macroUeBox = Box (-distance * 0.5, distance * 1.5, -distance * 0.5, distance * 1.5, 1.5, 1.5);
+
+  // Command line arguments
+  CommandLine cmd;
+  cmd.AddValue ("numberOfUes", "Number of UEs", numberOfRandomUes);
+  cmd.AddValue ("simTime", "Total duration of the simulation (in seconds)", simTime);
+  cmd.AddValue ("generateSpectrumTrace", "if true, will generate a Spectrum Analyzer trace", generateSpectrumTrace);
+  cmd.AddValue ("generateRem", "if true, will generate a REM and then abort the simulation", generateRem);
+  cmd.AddValue ("remRbId", "Resource block Id, for which REM will be generated,"
+                "default value is -1, what means REM will be averaged from all RBs", remRbId);
+  cmd.AddValue ("runId", "runId", runId);
+  cmd.Parse (argc, argv);
+
+  RngSeedManager::SetSeed (1);
+  RngSeedManager::SetRun (runId);
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper> ();
+  lteHelper->SetEpcHelper (epcHelper);
+  lteHelper->SetHandoverAlgorithmType ("ns3::NoOpHandoverAlgorithm"); // disable automatic handover
+
+  Ptr<Node> pgw = epcHelper->GetPgwNode ();
+
+  // Create a single RemoteHost
+  NodeContainer remoteHostContainer;
+  remoteHostContainer.Create (1);
+  Ptr<Node> remoteHost = remoteHostContainer.Get (0);
+  InternetStackHelper internet;
+  internet.Install (remoteHostContainer);
+
+  // Create the Internet
+  PointToPointHelper p2ph;
+  p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
+  p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
+  p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
+  NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
+  Ipv4AddressHelper ipv4h;
+  ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
+  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
+  Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1);
+
+  // Routing of the Internet Host (towards the LTE network)
+  Ipv4StaticRoutingHelper ipv4RoutingHelper;
+  Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
+  // interface 0 is localhost, 1 is the p2p device
+  remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer randomUeNodes;
+  enbNodes.Create (3);
+  randomUeNodes.Create (numberOfRandomUes);
+
+  /*   the topology is the following:
+   *                 eNB3
+   *                /     \
+   *               /       \
+   *              /         \
+   *             /           \
+   *   distance /             \ distance
+   *           /      UEs      \
+   *          /                 \
+   *         /                   \
+   *        /                     \
+   *       /                       \
+   *   eNB1-------------------------eNB2
+   *                  distance
+   */
+
+  // Install Mobility Model
+  Ptr<ListPositionAllocator> enbPositionAlloc = CreateObject<ListPositionAllocator> ();
+  enbPositionAlloc->Add (Vector (0.0, 0.0, 0.0));                       // eNB1
+  enbPositionAlloc->Add (Vector (distance,  0.0, 0.0));                 // eNB2
+  enbPositionAlloc->Add (Vector (distance * 0.5, distance * 0.866, 0.0));   // eNB3
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (enbPositionAlloc);
+  mobility.Install (enbNodes);
+
+  Ptr<RandomBoxPositionAllocator> randomUePositionAlloc = CreateObject<RandomBoxPositionAllocator> ();
+  Ptr<UniformRandomVariable> xVal = CreateObject<UniformRandomVariable> ();
+  xVal->SetAttribute ("Min", DoubleValue (macroUeBox.xMin));
+  xVal->SetAttribute ("Max", DoubleValue (macroUeBox.xMax));
+  randomUePositionAlloc->SetAttribute ("X", PointerValue (xVal));
+  Ptr<UniformRandomVariable> yVal = CreateObject<UniformRandomVariable> ();
+  yVal->SetAttribute ("Min", DoubleValue (macroUeBox.yMin));
+  yVal->SetAttribute ("Max", DoubleValue (macroUeBox.yMax));
+  randomUePositionAlloc->SetAttribute ("Y", PointerValue (yVal));
+  Ptr<UniformRandomVariable> zVal = CreateObject<UniformRandomVariable> ();
+  zVal->SetAttribute ("Min", DoubleValue (macroUeBox.zMin));
+  zVal->SetAttribute ("Max", DoubleValue (macroUeBox.zMax));
+  randomUePositionAlloc->SetAttribute ("Z", PointerValue (zVal));
+  mobility.SetPositionAllocator (randomUePositionAlloc);
+  mobility.Install (randomUeNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer randomUeDevs;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+  lteHelper->SetSchedulerAttribute ("HarqEnabled",  BooleanValue (true));
+
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFfrDistributedAlgorithm");
+  lteHelper->SetFfrAlgorithmAttribute ("CalculationInterval", TimeValue (MilliSeconds (200)));
+  lteHelper->SetFfrAlgorithmAttribute ("RsrpDifferenceThreshold", UintegerValue (5));
+  lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgeRbNum", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB_3));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+
+  lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
+
+  //ns3::LteFfrDistributedAlgorithm works with Absolute Mode Uplink Power Control
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  randomUeDevs = lteHelper->InstallUeDevice (randomUeNodes);
+
+  // Add X2 inteface
+  lteHelper->AddX2Interface (enbNodes);
+
+
+  NodeContainer ueNodes;
+  ueNodes.Add (randomUeNodes);
+  NetDeviceContainer ueDevs;
+  ueDevs.Add (randomUeDevs);
+
+  // Install the IP stack on the UEs
+  internet.Install (ueNodes);
+  Ipv4InterfaceContainer ueIpIfaces;
+  ueIpIfaces = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevs));
+  // Assign IP address to UEs, and install applications
+  for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
+    {
+      Ptr<Node> ueNode = ueNodes.Get (u);
+      // Set the default gateway for the UE
+      Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
+      ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
+    }
+
+  // Attach a UE to a eNB
+  lteHelper->AttachToClosestEnb (ueDevs, enbDevs);
+
+  // Install and start applications on UEs and remote host
+  uint16_t dlPort = 10000;
+  uint16_t ulPort = 20000;
+
+  // randomize a bit start times to avoid simulation artifacts
+  // (e.g., buffer overflows due to packet transmissions happening
+  // exactly at the same time)
+  Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable> ();
+  startTimeSeconds->SetAttribute ("Min", DoubleValue (0));
+  startTimeSeconds->SetAttribute ("Max", DoubleValue (0.010));
+
+  for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
+    {
+      Ptr<Node> ue = ueNodes.Get (u);
+      // Set the default gateway for the UE
+      Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ());
+      ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
+
+      for (uint32_t b = 0; b < 1; ++b)
+        {
+          ++dlPort;
+          ++ulPort;
+
+          ApplicationContainer clientApps;
+          ApplicationContainer serverApps;
+
+          UdpClientHelper dlClientHelper (ueIpIfaces.GetAddress (u), dlPort);
+          dlClientHelper.SetAttribute ("MaxPackets", UintegerValue (1000000));
+          dlClientHelper.SetAttribute ("Interval", TimeValue (MilliSeconds (1.0)));
+          clientApps.Add (dlClientHelper.Install (remoteHost));
+          PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory",
+                                               InetSocketAddress (Ipv4Address::GetAny (), dlPort));
+          serverApps.Add (dlPacketSinkHelper.Install (ue));
+
+
+          UdpClientHelper ulClientHelper (remoteHostAddr, ulPort);
+          ulClientHelper.SetAttribute ("MaxPackets", UintegerValue (1000000));
+          ulClientHelper.SetAttribute ("Interval", TimeValue (MilliSeconds (1.0)));
+          clientApps.Add (ulClientHelper.Install (ue));
+          PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory",
+                                               InetSocketAddress (Ipv4Address::GetAny (), ulPort));
+          serverApps.Add (ulPacketSinkHelper.Install (remoteHost));
+
+          Ptr<EpcTft> tft = Create<EpcTft> ();
+          EpcTft::PacketFilter dlpf;
+          dlpf.localPortStart = dlPort;
+          dlpf.localPortEnd = dlPort;
+          tft->Add (dlpf);
+          EpcTft::PacketFilter ulpf;
+          ulpf.remotePortStart = ulPort;
+          ulpf.remotePortEnd = ulPort;
+          tft->Add (ulpf);
+          EpsBearer bearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
+          lteHelper->ActivateDedicatedEpsBearer (ueDevs.Get (u), bearer, tft);
+
+          Time startTime = Seconds (startTimeSeconds->GetValue ());
+          serverApps.Start (startTime);
+          clientApps.Start (startTime);
+        }
+    }
+
+  //Spectrum analyzer
+  NodeContainer spectrumAnalyzerNodes;
+  spectrumAnalyzerNodes.Create (1);
+  SpectrumAnalyzerHelper spectrumAnalyzerHelper;
+
+  if (generateSpectrumTrace)
+    {
+      Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+      //position of Spectrum Analyzer
+      positionAlloc->Add (Vector (0.0, 0.0, 0.0));                              // eNB1
+//      positionAlloc->Add (Vector (distance,  0.0, 0.0));                        // eNB2
+//      positionAlloc->Add (Vector (distance*0.5, distance*0.866, 0.0));          // eNB3
+
+      MobilityHelper mobility;
+      mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+      mobility.SetPositionAllocator (positionAlloc);
+      mobility.Install (spectrumAnalyzerNodes);
+
+      Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+      Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+      spectrumAnalyzerHelper.SetChannel (dlChannel);
+      Ptr<SpectrumModel> sm = LteSpectrumValueHelper::GetSpectrumModel (100, bandwidth);
+      spectrumAnalyzerHelper.SetRxSpectrumModel (sm);
+      spectrumAnalyzerHelper.SetPhyAttribute ("Resolution", TimeValue (MicroSeconds (10)));
+      spectrumAnalyzerHelper.SetPhyAttribute ("NoisePowerSpectralDensity", DoubleValue (1e-15));     // -120 dBm/Hz
+      spectrumAnalyzerHelper.EnableAsciiAll ("spectrum-analyzer-output");
+      spectrumAnalyzerHelper.Install (spectrumAnalyzerNodes);
+    }
+
+  Ptr<RadioEnvironmentMapHelper> remHelper;
+  if (generateRem)
+    {
+      PrintGnuplottableEnbListToFile ("enbs.txt");
+      PrintGnuplottableUeListToFile ("ues.txt");
+
+      remHelper = CreateObject<RadioEnvironmentMapHelper> ();
+      Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+      Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+      uint32_t dlChannelId = dlChannel->GetId ();
+      NS_LOG_INFO ("DL ChannelId: " << dlChannelId);
+      remHelper->SetAttribute ("ChannelPath", StringValue ("/ChannelList/1"));
+      remHelper->SetAttribute ("OutputFile", StringValue ("lena-frequency-reuse.rem"));
+      remHelper->SetAttribute ("XMin", DoubleValue (macroUeBox.xMin));
+      remHelper->SetAttribute ("XMax", DoubleValue (macroUeBox.xMax));
+      remHelper->SetAttribute ("YMin", DoubleValue (macroUeBox.yMin));
+      remHelper->SetAttribute ("YMax", DoubleValue (macroUeBox.yMax));
+      remHelper->SetAttribute ("Z", DoubleValue (1.5));
+      remHelper->SetAttribute ("XRes", UintegerValue (500));
+      remHelper->SetAttribute ("YRes", UintegerValue (500));
+
+      if (remRbId >= 0)
+        {
+          remHelper->SetAttribute ("UseDataChannel", BooleanValue (true));
+          remHelper->SetAttribute ("RbId", IntegerValue (remRbId));
+        }
+
+      remHelper->Install ();
+      // simulation will stop right after the REM has been generated
+    }
+  else
+    {
+      Simulator::Stop (Seconds (simTime));
+    }
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+  return 0;
+}
--- a/src/lte/examples/lena-dual-stripe.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/examples/lena-dual-stripe.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -299,6 +299,12 @@
                                        "if false, will run the simulation normally (without generating any REM)",
                                        ns3::BooleanValue (false),
                                        ns3::MakeBooleanChecker ());
+static ns3::GlobalValue g_remRbId ("remRbId",
+                                   "Resource Block Id of Data Channel, for which REM will be generated;"
+                                   "default value is -1, what means REM will be averaged from all RBs of "
+                                   "Control Channel",
+                                   ns3::IntegerValue (-1),
+                                   MakeIntegerChecker<int32_t> ());
 static ns3::GlobalValue g_epc ("epc",
                                "If true, will setup the EPC to simulate an end-to-end topology, "
                                "with real IP applications over PDCP and RLC UM (or RLC AM by changing "
@@ -366,6 +372,7 @@
 
   // the scenario parameters get their values from the global attributes defined above
   UintegerValue uintegerValue;
+  IntegerValue integerValue;
   DoubleValue doubleValue;
   BooleanValue booleanValue;
   StringValue stringValue;
@@ -415,6 +422,8 @@
   bool useUdp = booleanValue.Get ();
   GlobalValue::GetValueByName ("generateRem", booleanValue);
   bool generateRem = booleanValue.Get ();
+  GlobalValue::GetValueByName ("remRbId", integerValue);
+  int32_t remRbId = integerValue.Get ();
   GlobalValue::GetValueByName ("fadingTrace", stringValue);
   std::string fadingTrace = stringValue.Get ();
   GlobalValue::GetValueByName ("numBearersPerUe", uintegerValue);
@@ -832,6 +841,13 @@
       remHelper->SetAttribute ("YMin", DoubleValue (macroUeBox.yMin));
       remHelper->SetAttribute ("YMax", DoubleValue (macroUeBox.yMax));
       remHelper->SetAttribute ("Z", DoubleValue (1.5));
+
+      if (remRbId >= 0)
+        {
+          remHelper->SetAttribute ("UseDataChannel", BooleanValue (true));
+          remHelper->SetAttribute ("RbId", IntegerValue (remRbId));
+        }
+
       remHelper->Install ();
       // simulation will stop right after the REM has been generated
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/examples/lena-frequency-reuse.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,402 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/lte-module.h"
+#include "ns3/config-store.h"
+#include <ns3/buildings-helper.h>
+#include <ns3/spectrum-module.h>
+#include <ns3/log.h>
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("LenaFrequencyReuse");
+
+void
+PrintGnuplottableUeListToFile (std::string filename)
+{
+  std::ofstream outFile;
+  outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
+  if (!outFile.is_open ())
+    {
+      NS_LOG_ERROR ("Can't open file " << filename);
+      return;
+    }
+  for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
+    {
+      Ptr<Node> node = *it;
+      int nDevs = node->GetNDevices ();
+      for (int j = 0; j < nDevs; j++)
+        {
+          Ptr<LteUeNetDevice> uedev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
+          if (uedev)
+            {
+              Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
+              outFile << "set label \"" << uedev->GetImsi ()
+                      << "\" at " << pos.x << "," << pos.y << " left font \"Helvetica,4\" textcolor rgb \"grey\" front point pt 1 ps 0.3 lc rgb \"grey\" offset 0,0"
+                      << std::endl;
+            }
+        }
+    }
+}
+
+void
+PrintGnuplottableEnbListToFile (std::string filename)
+{
+  std::ofstream outFile;
+  outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
+  if (!outFile.is_open ())
+    {
+      NS_LOG_ERROR ("Can't open file " << filename);
+      return;
+    }
+  for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
+    {
+      Ptr<Node> node = *it;
+      int nDevs = node->GetNDevices ();
+      for (int j = 0; j < nDevs; j++)
+        {
+          Ptr<LteEnbNetDevice> enbdev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
+          if (enbdev)
+            {
+              Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
+              outFile << "set label \"" << enbdev->GetCellId ()
+                      << "\" at " << pos.x << "," << pos.y
+                      << " left font \"Helvetica,4\" textcolor rgb \"white\" front  point pt 2 ps 0.3 lc rgb \"white\" offset 0,0"
+                      << std::endl;
+            }
+        }
+    }
+}
+
+int main (int argc, char *argv[])
+{
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (true));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (true));
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  Config::SetDefault ("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue (true));
+
+  //Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+  uint32_t runId = 3;
+  uint16_t numberOfRandomUes = 0;
+  double simTime = 2.500;
+  bool generateSpectrumTrace = false;
+  bool generateRem = false;
+  int32_t remRbId = -1;
+  uint8_t bandwidth = 25;
+  double distance = 1000;
+  Box macroUeBox = Box (-distance * 0.5, distance * 1.5, -distance * 0.5, distance * 1.5, 1.5, 1.5);
+
+  // Command line arguments
+  CommandLine cmd;
+  cmd.AddValue ("numberOfUes", "Number of random UEs", numberOfRandomUes);
+  cmd.AddValue ("simTime", "Total duration of the simulation (in seconds)", simTime);
+  cmd.AddValue ("generateSpectrumTrace", "if true, will generate a Spectrum Analyzer trace", generateSpectrumTrace);
+  cmd.AddValue ("generateRem", "if true, will generate a REM and then abort the simulation", generateRem);
+  cmd.AddValue ("remRbId", "Resource Block Id, for which REM will be generated,"
+                "default value is -1, what means REM will be averaged from all RBs", remRbId);
+  cmd.AddValue ("runId", "runId", runId);
+  cmd.Parse (argc, argv);
+
+  RngSeedManager::SetSeed (1);
+  RngSeedManager::SetRun (runId);
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer centerUeNodes;
+  NodeContainer edgeUeNodes;
+  NodeContainer randomUeNodes;
+  enbNodes.Create (3);
+  centerUeNodes.Create (3);
+  edgeUeNodes.Create (3);
+  randomUeNodes.Create (numberOfRandomUes);
+
+
+/*   the topology is the following:
+ *                 eNB3
+ *                /     \
+ *               /       \
+ *              /         \
+ *             /           \
+ *   distance /             \ distance
+ *           /      UEs      \
+ *          /                 \
+ *         /                   \
+ *        /                     \
+ *       /                       \
+ *   eNB1-------------------------eNB2
+ *                  distance
+ */
+
+  // Install Mobility Model
+  Ptr<ListPositionAllocator> enbPositionAlloc = CreateObject<ListPositionAllocator> ();
+  enbPositionAlloc->Add (Vector (0.0, 0.0, 0.0));                       // eNB1
+  enbPositionAlloc->Add (Vector (distance,  0.0, 0.0));                 // eNB2
+  enbPositionAlloc->Add (Vector (distance * 0.5, distance * 0.866, 0.0));   // eNB3
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (enbPositionAlloc);
+  mobility.Install (enbNodes);
+
+
+  Ptr<ListPositionAllocator> edgeUePositionAlloc = CreateObject<ListPositionAllocator> ();
+  edgeUePositionAlloc->Add (Vector (distance * 0.5, distance * 0.28867, 0.0));  // edgeUE1
+  edgeUePositionAlloc->Add (Vector (distance * 0.5, distance * 0.28867, 0.0));  // edgeUE2
+  edgeUePositionAlloc->Add (Vector (distance * 0.5, distance * 0.28867, 0.0));  // edgeUE3
+  mobility.SetPositionAllocator (edgeUePositionAlloc);
+  mobility.Install (edgeUeNodes);
+
+
+  Ptr<ListPositionAllocator> centerUePositionAlloc = CreateObject<ListPositionAllocator> ();
+  centerUePositionAlloc->Add (Vector (0.0, 0.0, 0.0));                                      // centerUE1
+  centerUePositionAlloc->Add (Vector (distance,  0.0, 0.0));                            // centerUE2
+  centerUePositionAlloc->Add (Vector (distance * 0.5, distance * 0.866, 0.0));      // centerUE3
+  mobility.SetPositionAllocator (centerUePositionAlloc);
+  mobility.Install (centerUeNodes);
+
+
+  Ptr<RandomBoxPositionAllocator> randomUePositionAlloc = CreateObject<RandomBoxPositionAllocator> ();
+  Ptr<UniformRandomVariable> xVal = CreateObject<UniformRandomVariable> ();
+  xVal->SetAttribute ("Min", DoubleValue (macroUeBox.xMin));
+  xVal->SetAttribute ("Max", DoubleValue (macroUeBox.xMax));
+  randomUePositionAlloc->SetAttribute ("X", PointerValue (xVal));
+  Ptr<UniformRandomVariable> yVal = CreateObject<UniformRandomVariable> ();
+  yVal->SetAttribute ("Min", DoubleValue (macroUeBox.yMin));
+  yVal->SetAttribute ("Max", DoubleValue (macroUeBox.yMax));
+  randomUePositionAlloc->SetAttribute ("Y", PointerValue (yVal));
+  Ptr<UniformRandomVariable> zVal = CreateObject<UniformRandomVariable> ();
+  zVal->SetAttribute ("Min", DoubleValue (macroUeBox.zMin));
+  zVal->SetAttribute ("Max", DoubleValue (macroUeBox.zMax));
+  randomUePositionAlloc->SetAttribute ("Z", PointerValue (zVal));
+  mobility.SetPositionAllocator (randomUePositionAlloc);
+  mobility.Install (randomUeNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer edgeUeDevs;
+  NetDeviceContainer centerUeDevs;
+  NetDeviceContainer randomUeDevs;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+  lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
+
+  std::string frAlgorithmType = lteHelper->GetFfrAlgorithmType ();
+  NS_LOG_DEBUG ("FrAlgorithmType: " << frAlgorithmType);
+
+  if (frAlgorithmType == "ns3::LteFrHardAlgorithm")
+    {
+
+      //Nothing to configure here in automatic mode
+
+    }
+  else if (frAlgorithmType == "ns3::LteFrStrictAlgorithm")
+    {
+
+      lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (32));
+      lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+      lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (0));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
+
+      //ns3::LteFrStrictAlgorithm works with Absolute Mode Uplink Power Control
+      Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+    }
+  else if (frAlgorithmType == "ns3::LteFrSoftAlgorithm")
+    {
+
+      lteHelper->SetFfrAlgorithmAttribute ("AllowCenterUeUseEdgeSubBand", BooleanValue (true));
+      lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
+      lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+      lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (0));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
+
+      //ns3::LteFrSoftAlgorithm works with Absolute Mode Uplink Power Control
+      Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+    }
+  else if (frAlgorithmType == "ns3::LteFfrSoftAlgorithm")
+    {
+
+      lteHelper->SetFfrAlgorithmAttribute ("CenterRsrqThreshold", UintegerValue (30));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgeRsrqThreshold", UintegerValue (25));
+      lteHelper->SetFfrAlgorithmAttribute ("CenterAreaPowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
+      lteHelper->SetFfrAlgorithmAttribute ("MediumAreaPowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB_1dot77));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaPowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+      lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (1));
+      lteHelper->SetFfrAlgorithmAttribute ("MediumAreaTpc", UintegerValue (2));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
+
+      //ns3::LteFfrSoftAlgorithm works with Absolute Mode Uplink Power Control
+      Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+    }
+  else if (frAlgorithmType == "ns3::LteFfrEnhancedAlgorithm")
+    {
+
+      lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
+      lteHelper->SetFfrAlgorithmAttribute ("DlCqiThreshold", UintegerValue (10));
+      lteHelper->SetFfrAlgorithmAttribute ("UlCqiThreshold", UintegerValue (10));
+      lteHelper->SetFfrAlgorithmAttribute ("CenterAreaPowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaPowerOffset",
+                                           UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+      lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (0));
+      lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
+
+      //ns3::LteFfrEnhancedAlgorithm works with Absolute Mode Uplink Power Control
+      Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+    }
+  else if (frAlgorithmType == "ns3::LteFfrDistributedAlgorithm")
+    {
+
+      NS_FATAL_ERROR ("ns3::LteFfrDistributedAlgorithm not supported in this example. Please run lena-distributed-ffr");
+
+    }
+  else
+    {
+      lteHelper->SetFfrAlgorithmType ("ns3::LteFrNoOpAlgorithm");
+    }
+
+  lteHelper->SetFfrAlgorithmAttribute ("FrCellTypeId", UintegerValue (1));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
+
+  lteHelper->SetFfrAlgorithmAttribute ("FrCellTypeId", UintegerValue (2));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
+
+  lteHelper->SetFfrAlgorithmAttribute ("FrCellTypeId", UintegerValue (3));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (2)));
+
+  //FR algorithm reconfiguration if needed
+  PointerValue tmp;
+  enbDevs.Get (0)->GetAttribute ("LteFfrAlgorithm", tmp);
+  Ptr<LteFfrAlgorithm> ffrAlgorithm = DynamicCast<LteFfrAlgorithm> (tmp.GetObject ());
+  ffrAlgorithm->SetAttribute ("FrCellTypeId", UintegerValue (1));
+
+
+  //Install Ue Device
+  edgeUeDevs = lteHelper->InstallUeDevice (edgeUeNodes);
+  centerUeDevs = lteHelper->InstallUeDevice (centerUeNodes);
+  randomUeDevs = lteHelper->InstallUeDevice (randomUeNodes);
+
+  // Attach edge UEs to eNbs
+  for (uint32_t i = 0; i < edgeUeDevs.GetN (); i++)
+    {
+      lteHelper->Attach (edgeUeDevs.Get (i), enbDevs.Get (i));
+    }
+  // Attach center UEs to eNbs
+  for (uint32_t i = 0; i < centerUeDevs.GetN (); i++)
+    {
+      lteHelper->Attach (centerUeDevs.Get (i), enbDevs.Get (i));
+    }
+
+  // Attach UE to a eNB
+  lteHelper->AttachToClosestEnb (randomUeDevs, enbDevs);
+
+  // Activate a data radio bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (edgeUeDevs, bearer);
+  lteHelper->ActivateDataRadioBearer (centerUeDevs, bearer);
+  lteHelper->ActivateDataRadioBearer (randomUeDevs, bearer);
+
+  //Spectrum analyzer
+  NodeContainer spectrumAnalyzerNodes;
+  spectrumAnalyzerNodes.Create (1);
+  SpectrumAnalyzerHelper spectrumAnalyzerHelper;
+
+  if (generateSpectrumTrace)
+    {
+      Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+      //position of Spectrum Analyzer
+//	  positionAlloc->Add (Vector (0.0, 0.0, 0.0));                              // eNB1
+//	  positionAlloc->Add (Vector (distance,  0.0, 0.0));                        // eNB2
+      positionAlloc->Add (Vector (distance * 0.5, distance * 0.866, 0.0));          // eNB3
+
+      MobilityHelper mobility;
+      mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+      mobility.SetPositionAllocator (positionAlloc);
+      mobility.Install (spectrumAnalyzerNodes);
+
+      Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+      Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+      spectrumAnalyzerHelper.SetChannel (dlChannel);
+      Ptr<SpectrumModel> sm = LteSpectrumValueHelper::GetSpectrumModel (100, bandwidth);
+      spectrumAnalyzerHelper.SetRxSpectrumModel (sm);
+      spectrumAnalyzerHelper.SetPhyAttribute ("Resolution", TimeValue (MicroSeconds (10)));
+      spectrumAnalyzerHelper.SetPhyAttribute ("NoisePowerSpectralDensity", DoubleValue (1e-15));     // -120 dBm/Hz
+      spectrumAnalyzerHelper.EnableAsciiAll ("spectrum-analyzer-output");
+      spectrumAnalyzerHelper.Install (spectrumAnalyzerNodes);
+    }
+
+  Ptr<RadioEnvironmentMapHelper> remHelper;
+  if (generateRem)
+    {
+      PrintGnuplottableEnbListToFile ("enbs.txt");
+      PrintGnuplottableUeListToFile ("ues.txt");
+
+      remHelper = CreateObject<RadioEnvironmentMapHelper> ();
+      remHelper->SetAttribute ("ChannelPath", StringValue ("/ChannelList/0"));
+      remHelper->SetAttribute ("OutputFile", StringValue ("lena-frequency-reuse.rem"));
+      remHelper->SetAttribute ("XMin", DoubleValue (macroUeBox.xMin));
+      remHelper->SetAttribute ("XMax", DoubleValue (macroUeBox.xMax));
+      remHelper->SetAttribute ("YMin", DoubleValue (macroUeBox.yMin));
+      remHelper->SetAttribute ("YMax", DoubleValue (macroUeBox.yMax));
+      remHelper->SetAttribute ("Z", DoubleValue (1.5));
+      remHelper->SetAttribute ("XRes", UintegerValue (500));
+      remHelper->SetAttribute ("YRes", UintegerValue (500));
+      if (remRbId >= 0)
+        {
+          remHelper->SetAttribute ("UseDataChannel", BooleanValue (true));
+          remHelper->SetAttribute ("RbId", IntegerValue (remRbId));
+        }
+
+      remHelper->Install ();
+      // simulation will stop right after the REM has been generated
+    }
+  else
+    {
+      Simulator::Stop (Seconds (simTime));
+    }
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/examples/lena-uplink-power-control.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,100 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/lte-module.h"
+#include "ns3/config-store.h"
+#include <ns3/buildings-helper.h>
+
+using namespace ns3;
+
+/*
+ * This example show how to configure and how Uplink Power Control works.
+ */
+
+int main (int argc, char *argv[])
+{	
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::Alpha", DoubleValue (1.0));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+
+  uint8_t bandwidth = 25;
+  double d1 = 0;
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes;
+  enbNodes.Create (1);
+  ueNodes.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes);
+
+/*   the topology is the following:
+ *
+ *   eNB1-------------------------UE
+ *                  d1
+ */
+
+  // Install Mobility Model
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));   		// eNB1
+  positionAlloc->Add (Vector (d1, 0.0, 0.0));  		// UE1
+
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
+
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+  // Activate a data radio bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+
+  Simulator::Stop (Seconds (0.500));
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+  return 0;
+}
--- a/src/lte/examples/wscript	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/examples/wscript	Fri Sep 05 01:12:55 2014 +0200
@@ -43,3 +43,12 @@
     obj = bld.create_ns3_program('lena-simple-epc-emu',
                                  ['lte', 'emu'])
     obj.source = 'lena-simple-epc-emu.cc'
+    obj = bld.create_ns3_program('lena-frequency-reuse',
+                                 ['lte'])
+    obj.source = 'lena-frequency-reuse.cc'
+    obj = bld.create_ns3_program('lena-distributed-ffr',
+                                 ['lte'])
+    obj.source = 'lena-distributed-ffr.cc'
+    obj = bld.create_ns3_program('lena-uplink-power-control',
+                                 ['lte'])
+    obj.source = 'lena-uplink-power-control.cc'
--- a/src/lte/helper/lte-helper.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/helper/lte-helper.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -35,7 +35,7 @@
 #include <ns3/lte-enb-phy.h>
 #include <ns3/lte-ue-phy.h>
 #include <ns3/lte-spectrum-phy.h>
-#include <ns3/lte-sinr-chunk-processor.h>
+#include <ns3/lte-chunk-processor.h>
 #include <ns3/multi-model-spectrum-channel.h>
 #include <ns3/friis-spectrum-propagation-loss.h>
 #include <ns3/trace-fading-loss-model.h>
@@ -43,6 +43,7 @@
 #include <ns3/lte-enb-net-device.h>
 #include <ns3/lte-ue-net-device.h>
 #include <ns3/ff-mac-scheduler.h>
+#include <ns3/lte-ffr-algorithm.h>
 #include <ns3/lte-handover-algorithm.h>
 #include <ns3/lte-anr.h>
 #include <ns3/lte-rlc.h>
@@ -151,10 +152,18 @@
                    MakeStringAccessor (&LteHelper::SetSchedulerType,
                                        &LteHelper::GetSchedulerType),
                    MakeStringChecker ())
+    .AddAttribute ("FfrAlgorithm",
+                   "The type of FFR algorithm to be used for eNBs. "
+                   "The allowed values for this attributes are the type names "
+                   "of any class inheriting from ns3::LteFfrAlgorithm.",
+                   StringValue ("ns3::LteFrNoOpAlgorithm"),
+                   MakeStringAccessor (&LteHelper::SetFfrAlgorithmType,
+                                       &LteHelper::GetFfrAlgorithmType),
+                   MakeStringChecker ())
     .AddAttribute ("HandoverAlgorithm",
                    "The type of handover algorithm to be used for eNBs. "
                    "The allowed values for this attributes are the type names "
-                   "of any class inheriting from ns3::HandoverAlgorithm.",
+                   "of any class inheriting from ns3::LteHandoverAlgorithm.",
                    StringValue ("ns3::NoOpHandoverAlgorithm"),
                    MakeStringAccessor (&LteHelper::SetHandoverAlgorithmType,
                                        &LteHelper::GetHandoverAlgorithmType),
@@ -185,6 +194,12 @@
                    BooleanValue (true),
                    MakeBooleanAccessor (&LteHelper::m_isAnrEnabled),
                    MakeBooleanChecker ())
+    .AddAttribute ("UsePdschForCqiGeneration",
+                   "If true, DL-CQI will be calculated from PDCCH as signal and PDSCH as interference "
+                   "If false, DL-CQI will be calculated from PDCCH as signal and PDCCH as interference  ",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&LteHelper::m_usePdschForCqiGeneration),
+                   MakeBooleanChecker ())
   ;
   return tid;
 }
@@ -228,6 +243,27 @@
 }
 
 std::string
+LteHelper::GetFfrAlgorithmType () const
+{
+  return m_ffrAlgorithmFactory.GetTypeId ().GetName ();
+}
+
+void
+LteHelper::SetFfrAlgorithmType (std::string type)
+{
+  NS_LOG_FUNCTION (this << type);
+  m_ffrAlgorithmFactory = ObjectFactory ();
+  m_ffrAlgorithmFactory.SetTypeId (type);
+}
+
+void
+LteHelper::SetFfrAlgorithmAttribute (std::string n, const AttributeValue &v)
+{
+  NS_LOG_FUNCTION (this << n);
+  m_ffrAlgorithmFactory.Set (n, v);
+}
+
+std::string
 LteHelper::GetHandoverAlgorithmType () const
 {
   return m_handoverAlgorithmFactory.GetTypeId ().GetName ();
@@ -389,13 +425,17 @@
   ulPhy->SetHarqPhyModule (harq);
   phy->SetHarqPhyModule (harq);
 
-  Ptr<LteCtrlSinrChunkProcessor> pCtrl = Create<LteCtrlSinrChunkProcessor> (phy->GetObject<LtePhy> ());
+  Ptr<LteChunkProcessor> pCtrl = Create<LteChunkProcessor> ();
+  pCtrl->AddCallback (MakeCallback (&LteEnbPhy::GenerateCtrlCqiReport, phy));
   ulPhy->AddCtrlSinrChunkProcessor (pCtrl); // for evaluating SRS UL-CQI
 
-  Ptr<LteDataSinrChunkProcessor> pData = Create<LteDataSinrChunkProcessor> (ulPhy, phy);
+  Ptr<LteChunkProcessor> pData = Create<LteChunkProcessor> ();
+  pData->AddCallback (MakeCallback (&LteEnbPhy::GenerateDataCqiReport, phy));
+  pData->AddCallback (MakeCallback (&LteSpectrumPhy::UpdateSinrPerceived, ulPhy));
   ulPhy->AddDataSinrChunkProcessor (pData); // for evaluating PUSCH UL-CQI
 
-  Ptr<LteInterferencePowerChunkProcessor> pInterf = Create<LteInterferencePowerChunkProcessor> (phy);
+  Ptr<LteChunkProcessor> pInterf = Create<LteChunkProcessor> ();
+  pInterf->AddCallback (MakeCallback (&LteEnbPhy::ReportInterference, phy));
   ulPhy->AddInterferenceDataChunkProcessor (pInterf); // for interference power tracing
 
   dlPhy->SetChannel (m_downlinkChannel);
@@ -413,6 +453,7 @@
 
   Ptr<LteEnbMac> mac = CreateObject<LteEnbMac> ();
   Ptr<FfMacScheduler> sched = m_schedulerFactory.Create<FfMacScheduler> ();
+  Ptr<LteFfrAlgorithm> ffrAlgorithm = m_ffrAlgorithmFactory.Create<LteFfrAlgorithm> ();
   Ptr<LteHandoverAlgorithm> handoverAlgorithm = m_handoverAlgorithmFactory.Create<LteHandoverAlgorithm> ();
   Ptr<LteEnbRrc> rrc = CreateObject<LteEnbRrc> ();
 
@@ -463,6 +504,14 @@
   phy->SetLteEnbCphySapUser (rrc->GetLteEnbCphySapUser ());
   rrc->SetLteEnbCphySapProvider (phy->GetLteEnbCphySapProvider ());
 
+  //FFR SAP
+  sched->SetLteFfrSapProvider (ffrAlgorithm->GetLteFfrSapProvider ());
+  ffrAlgorithm->SetLteFfrSapUser (sched->GetLteFfrSapUser ());
+
+  rrc->SetLteFfrRrcSapProvider (ffrAlgorithm->GetLteFfrRrcSapProvider ());
+  ffrAlgorithm->SetLteFfrRrcSapUser (rrc->GetLteFfrRrcSapUser ());
+  //FFR SAP END
+
   Ptr<LteEnbNetDevice> dev = m_enbNetDeviceFactory.Create<LteEnbNetDevice> ();
   dev->SetNode (n);
   dev->SetAttribute ("CellId", UintegerValue (cellId)); 
@@ -471,6 +520,7 @@
   dev->SetAttribute ("FfMacScheduler", PointerValue (sched));
   dev->SetAttribute ("LteEnbRrc", PointerValue (rrc)); 
   dev->SetAttribute ("LteHandoverAlgorithm", PointerValue (handoverAlgorithm));
+  dev->SetAttribute ("LteFfrAlgorithm", PointerValue (ffrAlgorithm));
 
   if (m_isAnrEnabled)
     {
@@ -544,18 +594,31 @@
   ulPhy->SetHarqPhyModule (harq);
   phy->SetHarqPhyModule (harq);
 
-  Ptr<LteRsReceivedPowerChunkProcessor> pRs = Create<LteRsReceivedPowerChunkProcessor> (phy->GetObject<LtePhy> ());
+  Ptr<LteChunkProcessor> pRs = Create<LteChunkProcessor> ();
+  pRs->AddCallback (MakeCallback (&LteUePhy::ReportRsReceivedPower, phy));
   dlPhy->AddRsPowerChunkProcessor (pRs);
 
-  Ptr<LteInterferencePowerChunkProcessor> pInterf = Create<LteInterferencePowerChunkProcessor> (phy);
+  Ptr<LteChunkProcessor> pInterf = Create<LteChunkProcessor> ();
+  pInterf->AddCallback (MakeCallback (&LteUePhy::ReportInterference, phy));
   dlPhy->AddInterferenceCtrlChunkProcessor (pInterf); // for RSRQ evaluation of UE Measurements
 
-  Ptr<LteCtrlSinrChunkProcessor> pCtrl = Create<LteCtrlSinrChunkProcessor> (phy->GetObject<LtePhy> (), dlPhy);
+  Ptr<LteChunkProcessor> pCtrl = Create<LteChunkProcessor> ();
+  pCtrl->AddCallback (MakeCallback (&LteUePhy::GenerateCtrlCqiReport, phy));
+  pCtrl->AddCallback (MakeCallback (&LteSpectrumPhy::UpdateSinrPerceived, dlPhy));
   dlPhy->AddCtrlSinrChunkProcessor (pCtrl);
 
-  Ptr<LteDataSinrChunkProcessor> pData = Create<LteDataSinrChunkProcessor> (dlPhy);
+  Ptr<LteChunkProcessor> pData = Create<LteChunkProcessor> ();
+  pData->AddCallback (MakeCallback (&LteSpectrumPhy::UpdateSinrPerceived, dlPhy));
   dlPhy->AddDataSinrChunkProcessor (pData);
 
+  Ptr<LteChunkProcessor> pDataInterf = Create<LteChunkProcessor> ();
+  if (m_usePdschForCqiGeneration)
+    {
+      pDataInterf->AddCallback (MakeCallback (&LteUePhy::ReportDataInterference, phy));
+    }
+
+  dlPhy->AddInterferenceDataChunkProcessor (pDataInterf);
+
   dlPhy->SetChannel (m_downlinkChannel);
   ulPhy->SetChannel (m_uplinkChannel);
 
@@ -926,7 +989,7 @@
   LogComponentEnable ("LteSpectrumValueHelper", LOG_LEVEL_ALL);
   LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
   LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
-  LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
+  LogComponentEnable ("LteChunkProcessor", LOG_LEVEL_ALL);
 
   std::string propModelStr = m_dlPathlossModelFactory.GetTypeId ().GetName ().erase (0,5).c_str ();
   LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
--- a/src/lte/helper/lte-helper.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/helper/lte-helper.h	Fri Sep 05 01:12:55 2014 +0200
@@ -114,6 +114,26 @@
 
   /**
    *
+   * \param type the type of FFR algorithm to be used for the eNBs
+   */
+  void SetFfrAlgorithmType (std::string type);
+
+  /**
+   *
+   * \return the FFR algorithm type
+   */
+  std::string GetFfrAlgorithmType () const;
+
+  /**
+   * set an attribute for the FFR algorithm to be created
+   *
+   * \param n the name of the attribute
+   * \param v the value of the attribute
+   */
+  void SetFfrAlgorithmAttribute (std::string n, const AttributeValue &v);
+
+  /**
+   *
    * \param type the type of handover algorithm to be used for the eNBs
    */
   void SetHandoverAlgorithmType (std::string type);
@@ -538,6 +558,7 @@
   Ptr<Object> m_uplinkPathlossModel;
 
   ObjectFactory m_schedulerFactory;
+  ObjectFactory m_ffrAlgorithmFactory;
   ObjectFactory m_handoverAlgorithmFactory;
   ObjectFactory m_propagationModelFactory;
   ObjectFactory m_enbNetDeviceFactory;
@@ -570,6 +591,8 @@
 
   bool m_useIdealRrc;
   bool m_isAnrEnabled;
+
+  bool m_usePdschForCqiGeneration;
 };
 
 
--- a/src/lte/helper/lte-hex-grid-enb-topology-helper.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/helper/lte-hex-grid-enb-topology-helper.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -139,18 +139,21 @@
 	case 0:
 	  antennaOrientation = 0;
 	  x += m_offset;
+	  m_lteHelper->SetFfrAlgorithmAttribute("FrCellTypeId", UintegerValue (1));
 	  break;
 	  
 	case 1:
 	  antennaOrientation = 120;
 	  x -= m_offset/2.0;
 	  y += m_offset*xydfactor;
+	  m_lteHelper->SetFfrAlgorithmAttribute("FrCellTypeId", UintegerValue (2));
 	  break;
 	  
 	case 2:
 	  antennaOrientation = -120;
 	  x -= m_offset/2.0;
 	  y -= m_offset*xydfactor;
+	  m_lteHelper->SetFfrAlgorithmAttribute("FrCellTypeId", UintegerValue (3));
 	  break;
 	
           // no default, n%3 = 0, 1, 2
--- a/src/lte/helper/radio-environment-map-helper.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/helper/radio-environment-map-helper.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -24,6 +24,7 @@
 #include <ns3/abort.h>
 #include <ns3/log.h>
 #include <ns3/double.h>
+#include <ns3/integer.h>
 #include <ns3/uinteger.h>
 #include <ns3/string.h>
 #include <ns3/boolean.h>
@@ -133,6 +134,17 @@
                    MakeUintegerAccessor (&RadioEnvironmentMapHelper::SetBandwidth, 
                                          &RadioEnvironmentMapHelper::GetBandwidth),
                    MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("UseDataChannel",
+                   "If true, REM will be generated for PDSCH and for PDCCH otherwise ",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&RadioEnvironmentMapHelper::m_useDataChannel),
+                   MakeBooleanChecker ())
+    .AddAttribute ("RbId",
+                   "Resource block Id, for which REM will be generated,"
+                   "default value is -1, what means REM will be averaged from all RBs",
+                   IntegerValue (-1),
+                   MakeIntegerAccessor (&RadioEnvironmentMapHelper::m_rbId),
+                   MakeIntegerChecker<int32_t> ())
   ;
   return tid;
 }
@@ -189,9 +201,17 @@
       return;
     }
   
-  Simulator::Schedule (Seconds (0.0026), 
+  double startDelay = 0.0026;
+
+  if (m_useDataChannel)
+    {
+      //need time to start transmission of data channel
+      startDelay = 0.5001;
+    }
+
+  Simulator::Schedule (Seconds (startDelay),
                        &RadioEnvironmentMapHelper::DelayedInstall,
-                                   this);
+                       this);
 }
 
 
@@ -216,6 +236,8 @@
       p.bmm->AggregateObject (buildingInfo); // operation usually done by BuildingsHelper::Install
       p.phy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (m_earfcn, m_bandwidth));
       p.phy->SetMobility (p.bmm);
+      p.phy->SetUseDataChannel (m_useDataChannel);
+      p.phy->SetRbId (m_rbId);
       m_channel->AddRx (p.phy);
       m_rem.push_back (p);
     }
@@ -249,6 +271,7 @@
             }
         }      
     }
+
   Simulator::Schedule (Seconds (remIterationStartTime), 
                        &RadioEnvironmentMapHelper::Finalize,
                        this);
@@ -268,7 +291,7 @@
            y < ((x == xMax) ? yMax : m_yMax) + 0.5*m_yStep;
            y += m_yStep)
         {
-          NS_ASSERT (remIt != m_rem.end ());          
+          NS_ASSERT (remIt != m_rem.end ());
           remIt->bmm->SetPosition (Vector (x, y, m_z));
           BuildingsHelper::MakeConsistent (remIt->bmm);
           ++remIt;
--- a/src/lte/helper/radio-environment-map-helper.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/helper/radio-environment-map-helper.h	Fri Sep 05 01:12:55 2014 +0200
@@ -112,6 +112,9 @@
 
   std::ofstream m_outFile;
 
+  bool m_useDataChannel;
+  int32_t m_rbId;
+
 };
 
 
--- a/src/lte/model/cqa-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/cqa-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -270,6 +270,8 @@
   m_amc = CreateObject <LteAmc> ();
   m_cschedSapProvider = new CqaSchedulerMemberCschedSapProvider (this);
   m_schedSapProvider = new CqaSchedulerMemberSchedSapProvider (this);
+  m_ffrSapProvider = 0;
+  m_ffrSapUser = new MemberLteFfrSapUser<CqaFfMacScheduler> (this);
 }
 
 CqaFfMacScheduler::~CqaFfMacScheduler ()
@@ -290,6 +292,7 @@
   m_ulHarqProcessesDciBuffer.clear ();
   delete m_cschedSapProvider;
   delete m_schedSapProvider;
+  delete m_ffrSapUser;
 }
 
 TypeId
@@ -349,6 +352,18 @@
 }
 
 void
+CqaFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+CqaFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 CqaFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -785,6 +800,16 @@
   uint16_t rbgAllocatedNum = 0;
   std::set <uint16_t> rntiAllocated;
   rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
+
+  rbgMap = m_ffrSapProvider->GetAvailableDlRbg ();
+  for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbgAllocatedNum++;
+        }
+    }
+
   FfMacSchedSapUser::SchedDlConfigIndParameters ret;
 
   //   update UL HARQ proc id
@@ -796,8 +821,48 @@
 
 
   // RACH Allocation
+  uint16_t rbAllocatedNum = 0;
+  std::vector <bool> ulRbMap;
+  ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+  ulRbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+  uint8_t maxContinuousUlBandwidth = 0;
+  uint8_t tmpMinBandwidth = 0;
+  uint16_t ffrRbStartOffset = 0;
+  uint16_t tmpFfrRbStartOffset = 0;
+  uint16_t index = 0;
+
+  for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+          if (tmpMinBandwidth > maxContinuousUlBandwidth)
+            {
+              maxContinuousUlBandwidth = tmpMinBandwidth;
+              ffrRbStartOffset = tmpFfrRbStartOffset;
+            }
+          tmpMinBandwidth = 0;
+        }
+      else
+        {
+          if (tmpMinBandwidth == 0)
+            {
+              tmpFfrRbStartOffset = index;
+            }
+          tmpMinBandwidth++;
+        }
+      index++;
+    }
+
+  if (tmpMinBandwidth > maxContinuousUlBandwidth)
+    {
+      maxContinuousUlBandwidth = tmpMinBandwidth;
+      ffrRbStartOffset = tmpFfrRbStartOffset;
+    }
+
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
   uint16_t rbStart = 0;
+  rbStart = ffrRbStartOffset;
   std::vector <struct RachListElement_s>::iterator itRach;
   for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
     {
@@ -812,7 +877,7 @@
       uint16_t rbLen = 1;
       uint16_t tbSizeBits = 0;
       // find lowest TB size that fits UL grant estimated size
-      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
+      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
         {
           rbLen++;
           tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
@@ -1019,7 +1084,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % numberOfRBGs;
                 }
               if (j == dciRbg.size ())
                 {
@@ -1037,7 +1102,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1287,7 +1352,9 @@
   for (int i = 0; i <  numberOfRBGs; i++)
     {
       if (rbgMap.at (i) == false)
-        availableRBGs.insert (i);
+        {
+          availableRBGs.insert (i);
+        }
     }
 
   t_it_HOLgroupToUEs itGBRgroups = map_GBRHOLgroupToUE.begin ();
@@ -1319,6 +1386,7 @@
 
       while (availableRBGs.size ()>0 and itCurrentGroup->second.size ()>0)
         {
+          bool currentRBchecked = false;
           int currentRB = *(availableRBGs.begin ());
           std::map<LteFlowId_t, CQI_value> UeToCQIValue;
           std::map<LteFlowId_t, double > UeToCoitaMetric;
@@ -1343,10 +1411,16 @@
 
               std::map <uint16_t, CqasFlowPerf_t>::iterator itStats;
 
+              if ((m_ffrSapProvider->IsDlRbgAvailableForUe (currentRB, flowId.m_rnti)) == false)
+                {
+                  continue;
+                }
+
               if (m_flowStatsDl.find (flowId.m_rnti) == m_flowStatsDl.end ())
                 {
                   continue;                               // TO DO:  check if this should be logged and how.
                 }
+              currentRBchecked = true;
 
               itStats = m_flowStatsDl.find (flowId.m_rnti);
               double tbr_weight = (*itStats).second.targetThroughput / (*itStats).second.lastAveragedThroughput;
@@ -1461,6 +1535,13 @@
                 }
             }
 
+          if (!currentRBchecked)
+            {
+              // erase current RBG from the list of available RBG
+              availableRBGs.erase (currentRB);
+              continue;
+            }
+
           qos_rb_and_CQI_assigned_to_lc s;
           s.cqi_value_for_lc = UeToCQIValue.find (userWithMaximumMetric)->second;
           s.resource_block_index = currentRB;
@@ -1595,6 +1676,8 @@
       newDci.m_rv.push_back (0);
       //}
 
+      newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
@@ -1677,6 +1760,7 @@
 CqaFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
+  m_ffrSapProvider->ReportDlCqiInfo (params);
 
   for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
     {
@@ -1771,6 +1855,7 @@
   NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
 
   RefreshUlCqiMaps ();
+  m_ffrSapProvider->ReportUlCqiInfo (m_ueCqi);
 
   // Generate RBs map
   FfMacSchedSapUser::SchedUlConfigIndParameters ret;
@@ -1785,6 +1870,20 @@
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
 
   rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+
+  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+
+  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+        }
+    }
+
+  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
+  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
+
   // remove RACH allocation
   for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
     {
@@ -1897,7 +1996,9 @@
 
 
   // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
-  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
+
   if (rbPerFlow < 3)
     {
       rbPerFlow = 3;  // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
@@ -1951,6 +2052,7 @@
             }
         }
 
+      rbAllocated = 0;
       UlDciListElement_s uldci;
       uldci.m_rnti = (*it).first;
       uldci.m_rbLen = rbPerFlow;
@@ -1967,9 +2069,15 @@
                   free = false;
                   break;
                 }
+              if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
+                {
+                  free = false;
+                  break;
+                }
             }
           if (free)
             {
+        	  NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
               uldci.m_rbStart = rbAllocated;
 
               for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
@@ -1998,13 +2106,14 @@
       if (!allocated)
         {
           // unable to allocate new resource: finish scheduling
-          m_nextRntiUl = (*it).first;
-          if (ret.m_dciList.size () > 0)
-            {
-              m_schedSapUser->SchedUlConfigInd (ret);
-            }
-          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
-          return;
+//          m_nextRntiUl = (*it).first;
+//          if (ret.m_dciList.size () > 0)
+//            {
+//              m_schedSapUser->SchedUlConfigInd (ret);
+//            }
+//          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
+//          return;
+          break;
         }
 
 
--- a/src/lte/model/cqa-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/cqa-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -33,6 +33,7 @@
 #include <set>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -94,6 +95,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class CqaSchedulerMemberCschedSapProvider;
   friend class CqaSchedulerMemberSchedSapProvider;
 
@@ -241,6 +246,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/fdbet-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/fdbet-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -296,6 +296,18 @@
 }
 
 void
+FdBetFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+FdBetFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 FdBetFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -406,7 +418,7 @@
 FdBetFfMacScheduler::DoCschedUeReleaseReq (const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
-  
+
   m_uesTxMode.erase (params.m_rnti);
   m_dlHarqCurrentProcessId.erase (params.m_rnti);
   m_dlHarqProcessesStatus.erase  (params.m_rnti);
@@ -601,14 +613,14 @@
   NS_LOG_FUNCTION (this);
 
   std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
-  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers ++)
+  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers++)
     {
       for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
         {
           if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
             {
               // reset HARQ process
-              
+
               NS_LOG_DEBUG (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
               std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
               if (itStat == m_dlHarqProcessesStatus.end ())
@@ -624,7 +636,7 @@
             }
         }
     }
-  
+
 }
 
 
@@ -882,7 +894,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -900,7 +912,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1029,7 +1041,7 @@
               NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*itFlow).first);
             }
           continue;
-       }
+        }
 
       estAveThr.insert (std::pair <uint16_t, double> ((*itFlow).first, (*itFlow).second.lastAveragedThroughput));
     }
@@ -1047,8 +1059,8 @@
             }
           rbgPerRntiLog.insert (std::pair<uint16_t, int> ((*it).first, 1));
         }
-      
-    
+
+
       // The scheduler tries the best to achieve the equal throughput among all UEs
       int i = 0;
       do 
@@ -1069,7 +1081,7 @@
                 {
                   (*itMap).second.push_back (i);
                 }
-          
+
               // caculate expected throughput for current UE
               std::map <uint16_t,uint8_t>::iterator itCqi;
               itCqi = m_p10CqiRxed.find ((*itMax).first);
@@ -1092,7 +1104,7 @@
                       mcs.push_back (m_amc->GetMcsFromCqi ((*itCqi).second));
                     }
                 }
-          
+
               std::map <uint16_t,int>::iterator itRbgPerRntiLog;
               itRbgPerRntiLog = rbgPerRntiLog.find ((*itMax).first);
               std::map <uint16_t, fdbetsFlowPerf_t>::iterator itPastAveThr;
@@ -1104,12 +1116,12 @@
                   bytesTxed += tbSize;
                 }
               double expectedAveThr = ((1.0 - (1.0 / m_timeWindow)) * (*itPastAveThr).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)(bytesTxed / 0.001));
-          
+
               int rbgPerRnti = (*itRbgPerRntiLog).second;
               rbgPerRnti++;
-              rbgPerRntiLog[(*itMax).first] = rbgPerRnti;   
+              rbgPerRntiLog[(*itMax).first] = rbgPerRnti;
               estAveThr[(*itMax).first] = expectedAveThr;
-          
+
               // find new UE with largest priority metric
               metricMax = 0.0;
               for (it = estAveThr.begin (); it != estAveThr.end (); it++)
@@ -1121,13 +1133,13 @@
                       metricMax = metric;
                     }
                 } // end for estAveThr
-        
+
               rbgMap.at (i) = true;
-    
-          } // end for free RBGs
-    
+
+            } // end for free RBGs
+
           i++;
-      
+
         } 
       while ( i < rbgNum ); // end for RBGs
 
@@ -1240,6 +1252,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = 1; //1 is mapped to 0 in Accumulated Mode and to -1 in Absolute Mode
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
@@ -1307,7 +1321,7 @@
   NS_LOG_FUNCTION (this);
 
   m_rachList = params.m_rachList;
-  
+
   return;
 }
 
@@ -1438,7 +1452,7 @@
     {
       //   Process UL HARQ feedback
       for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
-        {        
+        {
           if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
             {
               // retx correspondent block: retrieve the UL-DCI
@@ -1501,7 +1515,7 @@
               ret.m_dciList.push_back (dci);
               rntiAllocated.insert (dci.m_rnti);
             }
-            else
+          else
             {
               NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
             }
@@ -1528,7 +1542,7 @@
           m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
           m_schedSapUser->SchedUlConfigInd (ret);
         }
-        
+
       return;  // no flows to be scheduled
     }
 
@@ -1584,7 +1598,7 @@
           if (rbPerFlow < 3)
             {
               // terminate allocation
-              rbPerFlow = 0;      
+              rbPerFlow = 0;
             }
         }
 
@@ -1628,7 +1642,7 @@
               if (rbPerFlow < 3)
                 {
                   // terminate allocation
-                  rbPerFlow = 0;                 
+                  rbPerFlow = 0;
                 }
             }
         }
@@ -1676,8 +1690,8 @@
 
           // translate SINR -> cqi: WILD ACK: same as DL
           double s = log2 ( 1 + (
-                                 std::pow (10, minSinr / 10 )  /
-                                 ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
+                              std::pow (10, minSinr / 10 )  /
+                              ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
           cqi = m_amc->GetCqiFromSpectralEfficiency (s);
           if (cqi == 0)
             {
@@ -1824,7 +1838,7 @@
               uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
               buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
             }
-          
+
           uint16_t rnti = params.m_macCeList.at (i).m_rnti;
           NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
           it = m_ceBsrRxed.find (rnti);
@@ -2088,7 +2102,7 @@
       // Update status queue
       if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
         {
-           (*it).second.m_rlcStatusPduSize = 0;
+          (*it).second.m_rlcStatusPduSize = 0;
         }
       else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
         {
@@ -2103,7 +2117,7 @@
               // overestimate RLC overhead rather than
               // underestimate it and risk unneeded
               // segmentation which increases delay 
-              rlcOverhead = 4;                                  
+              rlcOverhead = 4;
             }
           else
             {
@@ -2116,7 +2130,7 @@
               (*it).second.m_rlcTransmissionQueueSize = 0;
             }
           else
-            {                    
+            {
               (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
             }
         }
--- a/src/lte/model/fdbet-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/fdbet-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -30,7 +30,7 @@
 #include <map>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -94,6 +94,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class FdBetSchedulerMemberCschedSapProvider;
   friend class FdBetSchedulerMemberSchedSapProvider;
 
@@ -240,6 +244,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/fdmt-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/fdmt-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -295,6 +295,18 @@
 }
 
 void
+FdMtFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+FdMtFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 FdMtFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -870,7 +882,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -888,7 +900,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1246,6 +1258,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = 1; //1 is mapped to 0 in Accumulated Mode and to -1 in Absolute Mode
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
--- a/src/lte/model/fdmt-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/fdmt-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -31,7 +31,7 @@
 #include <set>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -86,6 +86,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class FdMtSchedulerMemberCschedSapProvider;
   friend class FdMtSchedulerMemberSchedSapProvider;
 
@@ -232,6 +236,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/fdtbfq-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/fdtbfq-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -223,6 +223,8 @@
   m_amc = CreateObject <LteAmc> ();
   m_cschedSapProvider = new FdTbfqSchedulerMemberCschedSapProvider (this);
   m_schedSapProvider = new FdTbfqSchedulerMemberSchedSapProvider (this);
+  m_ffrSapProvider = 0;
+  m_ffrSapUser = new MemberLteFfrSapUser<FdTbfqFfMacScheduler> (this);
 }
 
 FdTbfqFfMacScheduler::~FdTbfqFfMacScheduler ()
@@ -243,6 +245,7 @@
   m_ulHarqProcessesDciBuffer.clear ();
   delete m_cschedSapProvider;
   delete m_schedSapProvider;
+  delete m_ffrSapUser;
 }
 
 TypeId
@@ -318,6 +321,18 @@
 }
 
 void
+FdTbfqFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+FdTbfqFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 FdTbfqFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -692,6 +707,16 @@
   uint16_t rbgAllocatedNum = 0;
   std::set <uint16_t> rntiAllocated;
   rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
+
+  rbgMap = m_ffrSapProvider->GetAvailableDlRbg ();
+  for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbgAllocatedNum++;
+        }
+    }
+
   FfMacSchedSapUser::SchedDlConfigIndParameters ret;
 
   //   update UL HARQ proc id
@@ -702,8 +727,48 @@
     }
 
   // RACH Allocation
+  uint16_t rbAllocatedNum = 0;
+  std::vector <bool> ulRbMap;
+  ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+  ulRbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+  uint8_t maxContinuousUlBandwidth = 0;
+  uint8_t tmpMinBandwidth = 0;
+  uint16_t ffrRbStartOffset = 0;
+  uint16_t tmpFfrRbStartOffset = 0;
+  uint16_t index = 0;
+
+  for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+          if (tmpMinBandwidth > maxContinuousUlBandwidth)
+            {
+              maxContinuousUlBandwidth = tmpMinBandwidth;
+              ffrRbStartOffset = tmpFfrRbStartOffset;
+            }
+          tmpMinBandwidth = 0;
+        }
+      else
+        {
+          if (tmpMinBandwidth == 0)
+            {
+              tmpFfrRbStartOffset = index;
+            }
+          tmpMinBandwidth++;
+        }
+      index++;
+    }
+
+  if (tmpMinBandwidth > maxContinuousUlBandwidth)
+    {
+      maxContinuousUlBandwidth = tmpMinBandwidth;
+      ffrRbStartOffset = tmpFfrRbStartOffset;
+    }
+
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
   uint16_t rbStart = 0;
+  rbStart = ffrRbStartOffset;
   std::vector <struct RachListElement_s>::iterator itRach;
   for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
     {
@@ -718,7 +783,7 @@
       uint16_t rbLen = 1;
       uint16_t tbSizeBits = 0;
       // find lowest TB size that fits UL grant estimated size
-      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
+      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
         {
           rbLen++;
           tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
@@ -925,7 +990,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -943,7 +1008,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1200,6 +1265,9 @@
               if ( rbgMap.at (k) == true) // this RBG is allocated in RACH procedure
                 continue;
 
+              if ((m_ffrSapProvider->IsDlRbgAvailableForUe (k, (*itMax).first)) == false)
+                continue;
+
               std::vector <uint8_t> sbCqi;
               if (itCqi == m_a30CqiRxed.end ())
                 {
@@ -1496,6 +1564,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
@@ -1544,6 +1614,7 @@
 FdTbfqFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
+  m_ffrSapProvider->ReportDlCqiInfo (params);
 
   for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
     {
@@ -1638,6 +1709,7 @@
   NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
 
   RefreshUlCqiMaps ();
+  m_ffrSapProvider->ReportUlCqiInfo (m_ueCqi);
 
   // Generate RBs map
   FfMacSchedSapUser::SchedUlConfigIndParameters ret;
@@ -1652,6 +1724,20 @@
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
 
   rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+
+  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+
+  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+        }
+    }
+
+  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
+  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
+
   // remove RACH allocation
   for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
     {
@@ -1763,7 +1849,9 @@
 
 
   // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
-  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
+
   if (rbPerFlow < 3)
     {
       rbPerFlow = 3;  // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
@@ -1817,6 +1905,7 @@
             }
         }
 
+      rbAllocated = 0;
       UlDciListElement_s uldci;
       uldci.m_rnti = (*it).first;
       uldci.m_rbLen = rbPerFlow;
@@ -1833,9 +1922,15 @@
                   free = false;
                   break;
                 }
+              if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
+                {
+                  free = false;
+                  break;
+                }
             }
           if (free)
             {
+              NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
               uldci.m_rbStart = rbAllocated;
 
               for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
@@ -1864,13 +1959,14 @@
       if (!allocated)
         {
           // unable to allocate new resource: finish scheduling
-          m_nextRntiUl = (*it).first;
-          if (ret.m_dciList.size () > 0)
-            {
-              m_schedSapUser->SchedUlConfigInd (ret);
-            }
-          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
-          return;
+//          m_nextRntiUl = (*it).first;
+//          if (ret.m_dciList.size () > 0)
+//            {
+//              m_schedSapUser->SchedUlConfigInd (ret);
+//            }
+//          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
+//          return;
+    	  break;
         }
 
 
--- a/src/lte/model/fdtbfq-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/fdtbfq-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -30,7 +30,7 @@
 #include <map>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -101,6 +101,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class FdTbfqSchedulerMemberCschedSapProvider;
   friend class FdTbfqSchedulerMemberSchedSapProvider;
 
@@ -247,6 +251,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -33,6 +33,8 @@
 class FfMacSchedSapUser;
 class FfMacCschedSapProvider;
 class FfMacSchedSapProvider;
+class LteFfrSapProvider;
+class LteFfrSapUser;
 
 /**
  * \ingroup lte
@@ -106,6 +108,21 @@
    */
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider () = 0;
 
+  //FFR SAPs
+  /**
+   *
+   * Set the Provider part of the LteFfrSap that this Scheduler will
+   * interact with
+   *
+   * \param s
+   */
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s) = 0;
+
+  /**
+   *
+   * \return the User part of the LteFfrSap provided by the FfrAlgorithm
+   */
+  virtual LteFfrSapUser* GetLteFfrSapUser () = 0;
   
 protected:
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-chunk-processor.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,89 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ * Modified by : Marco Miozzo <mmiozzo@cttc.es>
+ *        (move from CQI to Ctrl and Data SINR Chunk processors
+ */
+
+
+#include <ns3/log.h>
+#include <ns3/spectrum-value.h>
+#include "lte-chunk-processor.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteChunkProcessor");
+
+namespace ns3 {
+
+LteChunkProcessor::LteChunkProcessor ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+LteChunkProcessor::~LteChunkProcessor ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteChunkProcessor::AddCallback (LteChunkProcessorCallback c)
+{
+  NS_LOG_FUNCTION (this);
+  m_lteChunkProcessorCallbacks.push_back (c);
+}
+
+void
+LteChunkProcessor::Start ()
+{
+  NS_LOG_FUNCTION (this);
+  m_sumValues = 0;
+  m_totDuration = MicroSeconds (0);
+}
+
+
+void
+LteChunkProcessor::EvaluateChunk (const SpectrumValue& sinr, Time duration)
+{
+  NS_LOG_FUNCTION (this << sinr << duration);
+  if (m_sumValues == 0)
+    {
+      m_sumValues = Create<SpectrumValue> (sinr.GetSpectrumModel ());
+    }
+  (*m_sumValues) += sinr * duration.GetSeconds ();
+  m_totDuration += duration;
+}
+
+void
+LteChunkProcessor::End ()
+{
+  NS_LOG_FUNCTION (this);
+  if (m_totDuration.GetSeconds () > 0)
+    {
+      std::vector<LteChunkProcessorCallback>::iterator it;
+      for (it = m_lteChunkProcessorCallbacks.begin (); it != m_lteChunkProcessorCallbacks.end (); it++)
+        {
+          (*it)((*m_sumValues) / m_totDuration.GetSeconds ());
+        }
+    }
+  else
+    {
+      NS_LOG_WARN ("m_numSinr == 0");
+    }
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-chunk-processor.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,95 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009, 2010 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ * Modified by : Marco Miozzo <mmiozzo@cttc.es>
+ *        (move from CQI to Ctrl and Data SINR Chunk processors)
+ * Modified by : Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *        (removed all Lte***ChunkProcessor implementations
+ *        and created generic LteChunkProcessor)
+ */
+
+
+#ifndef LTE_CHUNK_PROCESSOR_H
+#define LTE_CHUNK_PROCESSOR_H
+
+#include <ns3/ptr.h>
+#include <ns3/nstime.h>
+#include <ns3/object.h>
+
+namespace ns3 {
+
+class SpectrumValue;
+
+typedef Callback< void, const SpectrumValue& > LteChunkProcessorCallback;
+
+/** 
+ * This abstract class is used to process the time-vs-frequency
+ * SINR/interference/power chunk of a received LTE signal
+ * which was calculated by the LteInterference object.
+ */
+class LteChunkProcessor : public SimpleRefCount<LteChunkProcessor>
+{
+public:
+  LteChunkProcessor ();
+  virtual ~LteChunkProcessor ();
+
+  /**
+    * \brief Add callback to list
+    *
+    * This function adds callback c to list. Each callback pass
+    * calculated value to its object and is called in
+    * LteChunkProcessor::End().
+    */
+  virtual void AddCallback (LteChunkProcessorCallback c);
+
+  /**
+    * \brief Clear internal variables
+    *
+    * This function clears internal variables in the beginning of
+    * calculation
+    */
+  virtual void Start ();
+
+  /**
+    * \brief Collect SpectrumValue and duration of signal
+    *
+    * Passed values are collected in m_sumValues and m_totDuration variables.
+    */
+  virtual void EvaluateChunk (const SpectrumValue& sinr, Time duration);
+
+  /**
+    * \brief Finish calculation and inform interested objects about calculated value
+    *
+    * During this function all callbacks from list are executed
+    * to inform interested object about calculated value. This
+    * function is called at the end of calculation.
+    */
+  virtual void End ();
+
+private:
+  Ptr<SpectrumValue> m_sumValues;
+  Time m_totDuration;
+
+  std::vector<LteChunkProcessorCallback> m_lteChunkProcessorCallbacks;
+};
+
+} // namespace ns3
+
+
+
+#endif /* LTE_CHUNK_PROCESSOR_H */
--- a/src/lte/model/lte-enb-cphy-sap.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-enb-cphy-sap.h	Fri Sep 05 01:12:55 2014 +0200
@@ -80,6 +80,14 @@
   virtual void RemoveUe (uint16_t rnti) = 0;
   
   /**
+   * Set the UE transmission power offset P_A
+   *
+   * \param rnti the UE id relative to this cell
+   * \param pa transmission power offset
+   */
+  virtual void SetPa (uint16_t rnti, double pa) = 0;
+
+  /**
    * \param rnti the RNTI of the user
    * \param txMode the transmissionMode of the user
    */
@@ -102,6 +110,12 @@
    * \param sib1 the System Information Block Type 1 to be sent on the BCH
    */
   virtual void SetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1) = 0;
+
+  /**
+   *
+   * \return Reference Signal Power for SIB2
+   */
+  virtual int8_t GetReferenceSignalPower () = 0;
 };
 
 
@@ -140,10 +154,12 @@
   virtual void SetEarfcn (uint16_t ulEarfcn, uint16_t dlEarfcn);
   virtual void AddUe (uint16_t rnti);
   virtual void RemoveUe (uint16_t rnti);
+  virtual void SetPa (uint16_t rnti, double pa);
   virtual void SetTransmissionMode (uint16_t  rnti, uint8_t txMode);
   virtual void SetSrsConfigurationIndex (uint16_t  rnti, uint16_t srsCi);
   virtual void SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
   virtual void SetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1);
+  virtual int8_t GetReferenceSignalPower ();
   
 private:
   MemberLteEnbCphySapProvider ();
@@ -199,6 +215,13 @@
 
 template <class C>
 void 
+MemberLteEnbCphySapProvider<C>::SetPa (uint16_t rnti, double pa)
+{
+  m_owner->DoSetPa (rnti, pa);
+}
+
+template <class C>
+void
 MemberLteEnbCphySapProvider<C>::SetTransmissionMode (uint16_t  rnti, uint8_t txMode)
 {
   m_owner->DoSetTransmissionMode (rnti, txMode);
@@ -225,7 +248,12 @@
   m_owner->DoSetSystemInformationBlockType1 (sib1);
 }
 
-
+template <class C>
+int8_t
+MemberLteEnbCphySapProvider<C>::GetReferenceSignalPower ()
+{
+  return m_owner->DoGetReferenceSignalPower ();
+}
 
 /**
  * Template for the implementation of the LteEnbCphySapUser as a member
--- a/src/lte/model/lte-enb-net-device.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-enb-net-device.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -40,6 +40,7 @@
 #include <ns3/ff-mac-scheduler.h>
 #include <ns3/lte-handover-algorithm.h>
 #include <ns3/lte-anr.h>
+#include <ns3/lte-ffr-algorithm.h>
 #include <ns3/ipv4-l3-protocol.h>
 #include <ns3/abort.h>
 #include <ns3/log.h>
@@ -72,6 +73,11 @@
                    PointerValue (),
                    MakePointerAccessor (&LteEnbNetDevice::m_anr),
                    MakePointerChecker <LteAnr> ())
+    .AddAttribute ("LteFfrAlgorithm",
+                   "The FFR algorithm associated to this EnbNetDevice",
+                   PointerValue (),
+                   MakePointerAccessor (&LteEnbNetDevice::m_ffrAlgorithm),
+                   MakePointerChecker <LteFfrAlgorithm> ())
     .AddAttribute ("LteEnbMac",
                    "The MAC associated to this EnbNetDevice",
                    PointerValue (),
@@ -170,6 +176,9 @@
       m_anr = 0;
     }
 
+  m_ffrAlgorithm->Dispose ();
+  m_ffrAlgorithm = 0;
+
   m_phy->Dispose ();
   m_phy = 0;
 
@@ -326,6 +335,8 @@
     {
       m_anr->Initialize ();
     }
+
+  m_ffrAlgorithm->Initialize ();
 }
 
 
--- a/src/lte/model/lte-enb-net-device.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-enb-net-device.h	Fri Sep 05 01:12:55 2014 +0200
@@ -42,7 +42,7 @@
 class FfMacScheduler;
 class LteHandoverAlgorithm;
 class LteAnr;
-
+class LteFfrAlgorithm;
 
 /**
  * \ingroup lte
@@ -200,6 +200,8 @@
 
   Ptr<LteAnr> m_anr;
 
+  Ptr<LteFfrAlgorithm> m_ffrAlgorithm;
+
   uint16_t m_cellId; /**< Cell Identifer. Part of the CGI, see TS 29.274, section 8.21.1  */
 
   uint8_t m_dlBandwidth; /**< downlink bandwidth in RBs */
--- a/src/lte/model/lte-enb-phy.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-enb-phy.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -75,7 +75,7 @@
   virtual void SetCellId (uint16_t cellId);
   virtual void SendLteControlMessage (Ptr<LteControlMessage> msg);
   virtual uint8_t GetMacChTtiDelay ();
-  
+
 
 private:
   LteEnbPhy* m_phy;
@@ -279,6 +279,13 @@
   return m_txPower;
 }
 
+int8_t
+LteEnbPhy::DoGetReferenceSignalPower () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_txPower;
+}
+
 void
 LteEnbPhy::SetNoiseFigure (double nf)
 {
@@ -400,6 +407,15 @@
   m_downlinkSpectrumPhy->SetTxPowerSpectralDensity (txPsd);
 }
 
+void
+LteEnbPhy::SetDownlinkSubChannelsWithPowerAllocation (std::vector<int> mask)
+{
+  NS_LOG_FUNCTION (this);
+  m_listOfDownlinkSubchannel = mask;
+  Ptr<SpectrumValue> txPsd = CreateTxPowerSpectralDensityWithPowerAllocation ();
+  m_downlinkSpectrumPhy->SetTxPowerSpectralDensity (txPsd);
+}
+
 std::vector<int>
 LteEnbPhy::GetDownlinkSubChannels (void)
 {
@@ -407,6 +423,21 @@
   return m_listOfDownlinkSubchannel;
 }
 
+void
+LteEnbPhy::GeneratePowerAllocationMap (uint16_t rnti, int rbId)
+{
+  NS_LOG_FUNCTION (this);
+  double rbgTxPower = m_txPower;
+
+  std::map<uint16_t, double>::iterator it = m_paMap.find (rnti);
+  if (it != m_paMap.end ())
+    {
+      rbgTxPower = m_txPower + it->second;
+    }
+
+  m_dlPowerAllocationMap.insert (std::pair<int, double> (rbId, rbgTxPower));
+}
+
 Ptr<SpectrumValue>
 LteEnbPhy::CreateTxPowerSpectralDensity ()
 {
@@ -417,6 +448,16 @@
   return psd;
 }
 
+Ptr<SpectrumValue>
+LteEnbPhy::CreateTxPowerSpectralDensityWithPowerAllocation ()
+{
+  NS_LOG_FUNCTION (this);
+
+  Ptr<SpectrumValue> psd = LteSpectrumValueHelper::CreateTxPowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_txPower, m_dlPowerAllocationMap, GetDownlinkSubChannels ());
+
+  return psd;
+}
+
 
 void
 LteEnbPhy::CalcChannelQualityForUe (std::vector <double> sinr, Ptr<LteSpectrumPhy> ue)
@@ -448,7 +489,7 @@
 {
   NS_LOG_FUNCTION (this);
   std::list<Ptr<LteControlMessage> >::iterator it;
-  for (it = msgList.begin (); it != msgList.end(); it++)
+  for (it = msgList.begin (); it != msgList.end (); it++)
     {
       switch ((*it)->GetMessageType ())
         {
@@ -490,7 +531,7 @@
                 m_enbPhySapUser->ReceiveLteControlMessage (*it);
               }
           }
-          break;          
+          break;
         default:
           NS_FATAL_ERROR ("Unexpected LteControlMessage type");
           break;
@@ -543,13 +584,13 @@
   if (m_srsPeriodicity>0)
     { 
       // might be 0 in case the eNB has no UEs attached
-        NS_ASSERT_MSG (m_nrFrames > 1, "the SRS index check code assumes that frameNo starts at 1");
+      NS_ASSERT_MSG (m_nrFrames > 1, "the SRS index check code assumes that frameNo starts at 1");
       NS_ASSERT_MSG (m_nrSubFrames > 0 && m_nrSubFrames <= 10, "the SRS index check code assumes that subframeNo starts at 1");
       m_currentSrsOffset = (((m_nrFrames-1)*10 + (m_nrSubFrames-1)) % m_srsPeriodicity);
     }
   NS_LOG_INFO ("-----sub frame " << m_nrSubFrames << "-----");
   m_harqPhyModule->SubframeIndication (m_nrFrames, m_nrSubFrames);
-  
+
   // update info on TB to be received
   std::list<UlDciLteControlMessage> uldcilist = DequeueUlDci ();
   std::list<UlDciLteControlMessage>::iterator dciIt = uldcilist.begin ();
@@ -558,7 +599,7 @@
     {
       std::set <uint16_t>::iterator it2;
       it2 = m_ueAttached.find ((*dciIt).GetDci ().m_rnti);
-      
+
       if (it2 == m_ueAttached.end ())
         {
           NS_LOG_ERROR ("UE not attached");
@@ -587,6 +628,7 @@
   // process the current burst of control messages
   std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
   m_dlDataRbMap.clear ();
+  m_dlPowerAllocationMap.clear ();
   if (ctrlMsg.size () > 0)
     {
       std::list<Ptr<LteControlMessage> >::iterator it;
@@ -608,6 +650,7 @@
                         {
                           m_dlDataRbMap.push_back ((i * GetRbgSize ()) + k);
                           //NS_LOG_DEBUG(this << " [enb]DL-DCI allocated PRB " << (i*GetRbgSize()) + k);
+                          GeneratePowerAllocationMap (dci->GetDci ().m_rnti, (i * GetRbgSize ()) + k );
                         }
                     }
                   mask = (mask << 1);
@@ -628,7 +671,7 @@
                   params.m_ndi = dci->GetDci ().m_ndi.at (i);
                   m_dlPhyTransmission (params);
                 }
-              
+
             }
           else if (msg->GetMessageType () == LteControlMessage::UL_DCI)
             {
@@ -665,16 +708,16 @@
 
         }
     }
-    
+
   SendControlChannels (ctrlMsg);
-  
+
   // send data frame
   Ptr<PacketBurst> pb = GetPacketBurst ();
   if (pb)
     {
       Simulator::Schedule (DL_CTRL_DELAY_FROM_SUBFRAME_START, // ctrl frame fixed to 3 symbols
-                       &LteEnbPhy::SendDataChannels,
-                       this,pb);
+                           &LteEnbPhy::SendDataChannels,
+                           this,pb);
     }
 
   // trigger the MAC
@@ -704,14 +747,14 @@
       pss = true;
     }
   m_downlinkSpectrumPhy->StartTxDlCtrlFrame (ctrlMsgList, pss);
-  
+
 }
 
 void
 LteEnbPhy::SendDataChannels (Ptr<PacketBurst> pb)
 {
   // set the current tx power spectral density
-  SetDownlinkSubChannels (m_dlDataRbMap);
+  SetDownlinkSubChannelsWithPowerAllocation (m_dlDataRbMap);
   // send the current burts of packets
   NS_LOG_LOGIC (this << " eNB start TX DATA");
   std::list<Ptr<LteControlMessage> > ctrlMsgList;
@@ -845,6 +888,9 @@
  
   bool success = AddUePhy (rnti);
   NS_ASSERT_MSG (success, "AddUePhy() failed");
+
+  // add default P_A value
+  DoSetPa (rnti, 0);
 }
 
 void 
@@ -854,8 +900,33 @@
  
   bool success = DeleteUePhy (rnti);
   NS_ASSERT_MSG (success, "DeleteUePhy() failed");
+
+  // remove also P_A value
+  std::map<uint16_t, double>::iterator it = m_paMap.find (rnti);
+  if (it != m_paMap.end ())
+    {
+      m_paMap.erase (it);
+    }
+
 }
 
+void
+LteEnbPhy::DoSetPa (uint16_t rnti, double pa)
+{
+  NS_LOG_FUNCTION (this << rnti);
+
+  std::map<uint16_t, double>::iterator it = m_paMap.find (rnti);
+
+  if (it == m_paMap.end ())
+    {
+      m_paMap.insert (std::pair<uint16_t, double> (rnti, pa));
+    }
+  else
+    {
+      it->second = pa;
+    }
+
+}
 
 FfMacSchedSapProvider::SchedUlCqiInfoReqParameters
 LteEnbPhy::CreateSrsCqiReport (const SpectrumValue& sinr)
@@ -867,15 +938,15 @@
   int i = 0;
   double srsSum = 0.0;
   for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++)
-  {
-    double sinrdb = 10 * log10 ((*it));
-    //       NS_LOG_DEBUG ("ULCQI RB " << i << " value " << sinrdb);
-    // convert from double to fixed point notation Sxxxxxxxxxxx.xxx
-    int16_t sinrFp = LteFfConverter::double2fpS11dot3 (sinrdb);
-    srsSum += (*it);
-    ulcqi.m_ulCqi.m_sinr.push_back (sinrFp);
-    i++;
-  }
+    {
+      double sinrdb = 10 * log10 ((*it));
+      //       NS_LOG_DEBUG ("ULCQI RB " << i << " value " << sinrdb);
+      // convert from double to fixed point notation Sxxxxxxxxxxx.xxx
+      int16_t sinrFp = LteFfConverter::double2fpS11dot3 (sinrdb);
+      srsSum += (*it);
+      ulcqi.m_ulCqi.m_sinr.push_back (sinrFp);
+      i++;
+    }
   // Insert the user generated the srs as a vendor specific parameter
   NS_LOG_DEBUG (this << " ENB RX UL-CQI of " << m_srsUeOffset.at (m_currentSrsOffset));
   VendorSpecificListElement_s vsp;
@@ -888,12 +959,12 @@
   CreateSrsReport (m_srsUeOffset.at (m_currentSrsOffset),
                    (i > 0) ? (srsSum / i) : DBL_MAX);
   return (ulcqi);
-  
+
 }
 
 
 void
-LteEnbPhy::CreateSrsReport(uint16_t rnti, double srs)
+LteEnbPhy::CreateSrsReport (uint16_t rnti, double srs)
 {
   NS_LOG_FUNCTION (this << rnti << srs);
   std::map <uint16_t,uint16_t>::iterator it = m_srsSampleCounterMap.find (rnti);
@@ -976,7 +1047,7 @@
       m_srsCounter.insert (std::pair<uint16_t, uint16_t> (rnti, GetSrsSubframeOffset (srcCi) + 1));
     }
   m_srsUeOffset.at (GetSrsSubframeOffset (srcCi)) = rnti;
-    
+
 }
 
 
--- a/src/lte/model/lte-enb-phy.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-enb-phy.h	Fri Sep 05 01:12:55 2014 +0200
@@ -48,7 +48,7 @@
 {
   friend class EnbMemberLteEnbPhySapProvider;
   friend class MemberLteEnbCphySapProvider<LteEnbPhy>;
-  
+
 public:
   /**
    * @warning the default constructor should not be used
@@ -104,6 +104,10 @@
    */
   double GetTxPower () const;
 
+  /**
+   * \return the transmission power in dBm
+   */
+  int8_t DoGetReferenceSignalPower () const;
 
   /**
    * \param pow the noise figure in dB
@@ -119,7 +123,7 @@
    * \param delay the TTI delay between MAC and channel
    */
   void SetMacChDelay (uint8_t delay);
-  
+
   /**
    * \returns the TTI delay between MAC and channel
    */
@@ -134,7 +138,7 @@
    * \return a pointer to the LteSpectrumPhy instance relative to the uplink
    */
   Ptr<LteSpectrumPhy> GetUlSpectrumPhy () const;
-  
+
 
   /**
    * \brief set the resource blocks (a.k.a. sub channels) to be used in the downlink for transmission
@@ -146,7 +150,16 @@
    */
   void SetDownlinkSubChannels (std::vector<int> mask );
 
-
+  /**
+   * \brief set the resource blocks (a.k.a. sub channels) and its power
+   * to be used in the downlink for transmission
+   *
+   * \param mask a vector of integers, if the i-th value is j it means
+   * that the j-th resource block is used for transmission in the
+   * downlink. If there is no i such that the value of the i-th
+   * element is j, it means that RB j is not used.
+   */
+  void SetDownlinkSubChannelsWithPowerAllocation (std::vector<int> mask);
   /**
    * 
    * \return  a vector of integers, if the i-th value is j it means
@@ -156,12 +169,27 @@
    */
   std::vector<int> GetDownlinkSubChannels (void);
 
+
+  /**
+   * \brief Generate power allocation map (i.e. tx power level for each RB)
+   *
+   * \param rnti indicates which UE will occupy this RB
+   * \param rbId indicates which RB UE is using,
+   * power level for this RB is power level of UE
+   */
+  void GeneratePowerAllocationMap (uint16_t rnti, int rbId);
+
   /**
    * \brief Create the PSD for TX
    */
   virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity ();
 
   /**
+   * \brief Create the PSD for TX with power allocation for each RB
+   */
+  virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensityWithPowerAllocation ();
+
+  /**
    * \brief Calculate the channel quality for a given UE
    * \param sinr a list of computed SINR
    * \param ue the UE
@@ -181,7 +209,7 @@
   * \return UL CQI feedback in the format usable by an FF MAC scheduler
   */
   FfMacSchedSapProvider::SchedUlCqiInfoReqParameters CreatePuschCqiReport (const SpectrumValue& sinr);
-  
+
   /**
   * \brief Create the UL CQI feedback from SINR values perceived at
   * the physical layer with the SRS signal received from eNB
@@ -195,18 +223,18 @@
   * \param ctrlMsgList the list of control messages of PDCCH
   */
   void SendControlChannels (std::list<Ptr<LteControlMessage> > ctrlMsgList);
-  
+
   /**
   * \brief Send the PDSCH
   * \param pb the PacketBurst to be sent
   */
   void SendDataChannels (Ptr<PacketBurst> pb);
-  
+
   /**
   * \param m the UL-CQI to be queued
   */
   void QueueUlDci (UlDciLteControlMessage m);
-  
+
   /**
   * \returns the list of UL-CQI to be processed
   */
@@ -234,7 +262,7 @@
    * \brief PhySpectrum received a new PHY-PDU
    */
   void PhyPduReceived (Ptr<Packet> p);
-  
+
   /**
   * \brief PhySpectrum received a new list of LteControlMessage
   */
@@ -261,31 +289,39 @@
   // LteEnbCphySapProvider forwarded methods
   void DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
   void DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
-  void DoAddUe (uint16_t rnti);  
-  void DoRemoveUe (uint16_t rnti);  
+  void DoAddUe (uint16_t rnti);
+  void DoRemoveUe (uint16_t rnti);
+  void DoSetPa (uint16_t rnti, double pa);
   void DoSetTransmissionMode (uint16_t  rnti, uint8_t txMode);
-  void DoSetSrsConfigurationIndex (uint16_t  rnti, uint16_t srcCi);  
+  void DoSetSrsConfigurationIndex (uint16_t  rnti, uint16_t srcCi);
   void DoSetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
   void DoSetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1);
 
   // LteEnbPhySapProvider forwarded methods
-  void DoSendMacPdu (Ptr<Packet> p);  
-  void DoSendLteControlMessage (Ptr<LteControlMessage> msg);  
-  uint8_t DoGetMacChTtiDelay ();  
+  void DoSendMacPdu (Ptr<Packet> p);
+  void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
+  uint8_t DoGetMacChTtiDelay ();
 
   bool AddUePhy (uint16_t rnti);
 
   bool DeleteUePhy (uint16_t rnti);
 
-  void CreateSrsReport(uint16_t rnti, double srs);
+  void CreateSrsReport (uint16_t rnti, double srs);
 
 
   std::set <uint16_t> m_ueAttached;
-  
+
+
+  // P_A per UE RNTI
+  std::map <uint16_t,double> m_paMap;
+
+  // DL power allocation map
+  std::map <int, double> m_dlPowerAllocationMap;
+
   std::vector <int> m_listOfDownlinkSubchannel;
-  
+
   std::vector <int> m_dlDataRbMap;
-  
+
   std::vector< std::list<UlDciLteControlMessage> > m_ulDciQueue; // for storing info on future receptions
 
   LteEnbPhySapProvider* m_enbPhySapProvider;
@@ -293,10 +329,10 @@
 
   LteEnbCphySapProvider* m_enbCphySapProvider;
   LteEnbCphySapUser* m_enbCphySapUser;
-  
+
   uint32_t m_nrFrames;
   uint32_t m_nrSubFrames;
-  
+
   uint16_t m_srsPeriodicity;
   Time m_srsStartTime;
   std::map <uint16_t,uint16_t> m_srsCounter;
@@ -330,7 +366,7 @@
    * PhyTrasmissionStatParameters see lte-common.h
    */
   TracedCallback<PhyTransmissionStatParameters> m_dlPhyTransmission;
-  
+
 };
 
 
--- a/src/lte/model/lte-enb-rrc.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-enb-rrc.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -139,7 +139,7 @@
     m_pendingRrcConnectionReconfiguration (false),
     m_sourceX2apId (0),
     m_sourceCellId (0),
-    m_needTransmissionModeConfiguration (false)
+    m_needPhyMacConfiguration (false)
 { 
   NS_LOG_FUNCTION (this);
 }
@@ -156,6 +156,8 @@
   m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex = m_rrc->GetNewSrsConfigurationIndex ();
   m_physicalConfigDedicated.soundingRsUlConfigDedicated.type = LteRrcSap::SoundingRsUlConfigDedicated::SETUP;
   m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsBandwidth = 0;
+  m_physicalConfigDedicated.havePdschConfigDedicated = true;
+  m_physicalConfigDedicated.pdschConfigDedicated.pa = LteRrcSap::PdschConfigDedicated::dB0;
 
   m_rrc->m_cmacSapProvider->AddUe (m_rnti);
   m_rrc->m_cphySapProvider->AddUe (m_rnti);
@@ -169,7 +171,7 @@
     rlc->SetRnti (m_rnti);
     rlc->SetLcId (lcid);
 
-    m_srb0 = CreateObject<LteSignalingRadioBearerInfo> ();  
+    m_srb0 = CreateObject<LteSignalingRadioBearerInfo> ();
     m_srb0->m_rlc = rlc;
     m_srb0->m_srbIdentity = 0;
     // no need to store logicalChannelConfig as SRB0 is pre-configured
@@ -179,7 +181,7 @@
     lcinfo.lcId = lcid;
     // leave the rest of lcinfo empty as CCCH (LCID 0) is pre-configured
     m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
-    
+
   }
 
   // setup the eNB side of SRB1; the UE side will be set up upon RRC connection establishment
@@ -198,7 +200,7 @@
     pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
     rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
 
-    m_srb1 = CreateObject<LteSignalingRadioBearerInfo> ();  
+    m_srb1 = CreateObject<LteSignalingRadioBearerInfo> ();
     m_srb1->m_rlc = rlc;
     m_srb1->m_pdcp = pdcp;
     m_srb1->m_srbIdentity = 1;
@@ -206,7 +208,7 @@
     m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps = 100;
     m_srb1->m_logicalChannelConfig.bucketSizeDurationMs = 100;
     m_srb1->m_logicalChannelConfig.logicalChannelGroup = 0;
-    
+
     LteEnbCmacSapProvider::LcInfo lcinfo;
     lcinfo.rnti = m_rnti;
     lcinfo.lcId = lcid;
@@ -230,7 +232,7 @@
   req.m_rnti = m_rnti;
   req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
   m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
-  
+
   // configure PHY
   m_rrc->m_cphySapProvider->SetTransmissionMode (m_rnti, m_physicalConfigDedicated.antennaInfo.transmissionMode);
   m_rrc->m_cphySapProvider->SetSrsConfigurationIndex (m_rnti, m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex);
@@ -328,7 +330,7 @@
   Ptr<LteDataRadioBearerInfo> drbInfo = CreateObject<LteDataRadioBearerInfo> ();
   uint8_t drbid = AddDataRadioBearerInfo (drbInfo);
   uint8_t lcid = Drbid2Lcid (drbid); 
-  uint8_t bid = Drbid2Bid (drbid);  
+  uint8_t bid = Drbid2Bid (drbid);
   NS_ASSERT_MSG ( bearerId == 0 || bid == bearerId, "bearer ID mismatch (" << (uint32_t) bid << " != " << (uint32_t) bearerId << ", the assumption that ID are allocated in the same way by MME and RRC is not valid any more");
   drbInfo->m_epsBearerIdentity = bid;
   drbInfo->m_drbIdentity = drbid;
@@ -343,7 +345,7 @@
       x2uTeidInfo.rnti = m_rnti;
       x2uTeidInfo.drbid = drbid;
       std::pair<std::map<uint32_t, LteEnbRrc::X2uTeidInfo>::iterator, bool>
-        ret = m_rrc->m_x2uTeidInfoMap.insert (std::pair<uint32_t, LteEnbRrc::X2uTeidInfo> (gtpTeid, x2uTeidInfo));
+      ret = m_rrc->m_x2uTeidInfoMap.insert (std::pair<uint32_t, LteEnbRrc::X2uTeidInfo> (gtpTeid, x2uTeidInfo));
       NS_ASSERT_MSG (ret.second == true, "overwriting a pre-existing entry in m_x2uTeidInfoMap");
     }
 
@@ -371,7 +373,7 @@
       rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
       drbInfo->m_pdcp = pdcp;
     }
-    
+
   LteEnbCmacSapProvider::LcInfo lcinfo;
   lcinfo.rnti = m_rnti;
   lcinfo.lcId = lcid;
@@ -383,7 +385,7 @@
   lcinfo.gbrUl = bearer.gbrQosInfo.gbrUl;
   lcinfo.gbrDl = bearer.gbrQosInfo.gbrDl;
   m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
-  
+
   if (rlcTypeId == LteRlcAm::GetTypeId ())
     {
       drbInfo->m_rlcConfig.choice =  LteRrcSap::RlcConfig::AM;
@@ -398,7 +400,7 @@
   drbInfo->m_logicalChannelConfig.logicalChannelGroup = m_rrc->GetLogicalChannelGroup (bearer);
   if (bearer.IsGbr ())
     {
-      drbInfo->m_logicalChannelConfig.prioritizedBitRateKbps = bearer.gbrQosInfo.gbrUl;      
+      drbInfo->m_logicalChannelConfig.prioritizedBitRateKbps = bearer.gbrQosInfo.gbrUl;
     }
   else
     {
@@ -418,7 +420,7 @@
        ++it)
     {
       m_drbsToBeStarted.push_back (it->first);
-    }    
+    }
 }
 
 void
@@ -518,7 +520,7 @@
         params.ueAggregateMaxBitRateDownlink = 200 * 1000;
         params.ueAggregateMaxBitRateUplink = 100 * 1000;
         params.bearers = GetErabList ();
-  
+
         LteRrcSap::HandoverPreparationInfo hpi;
         hpi.asConfig.sourceUeIdentity = m_rnti;
         hpi.asConfig.sourceDlCarrierFreq = m_rrc->m_dlEarfcn;
@@ -537,18 +539,18 @@
         hpi.asConfig.sourceSystemInformationBlockType2.freqInfo.ulCarrierFreq = m_rrc->m_ulEarfcn;
         hpi.asConfig.sourceSystemInformationBlockType2.freqInfo.ulBandwidth = m_rrc->m_ulBandwidth;
         params.rrcContext = m_rrc->m_rrcSapUser->EncodeHandoverPreparationInformation (hpi);
-  
+
         NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
         NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
         NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
         NS_LOG_LOGIC ("mmeUeS1apId = " << params.mmeUeS1apId);
         NS_LOG_LOGIC ("rrcContext   = " << params.rrcContext);
-  
+
         m_rrc->m_x2SapProvider->SendHandoverRequest (params);
         SwitchToState (HANDOVER_PREPARATION);
       }
-      break;      
-      
+      break;
+
     default:
       NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
       break;
@@ -560,7 +562,7 @@
 UeManager::RecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params)
 {
   NS_LOG_FUNCTION (this);
-  
+
   NS_ASSERT_MSG (params.notAdmittedBearers.empty (), "not admission of some bearers upon handover is not supported");
   NS_ASSERT_MSG (params.admittedBearers.size () == m_drbMap.size (), "not enough bearers in admittedBearers");
 
@@ -593,7 +595,7 @@
       if (0 != drbIt->second->m_rlc->GetObject<LteRlcAm> ())
         {
           LtePdcp::Status status = drbIt->second->m_pdcp->GetStatus ();
-          EpcX2Sap::ErabsSubjectToStatusTransferItem i;          
+          EpcX2Sap::ErabsSubjectToStatusTransferItem i;
           i.dlPdcpSn = status.txSn;
           i.ulPdcpSn = status.rxSn;
           sst.erabsSubjectToStatusTransferList.push_back (i);
@@ -627,9 +629,9 @@
     case CONNECTION_SETUP:
       NS_LOG_WARN ("not connected, discarding packet");
       return;
-      break;      
-      
-    case CONNECTED_NORMALLY:      
+      break;
+
+    case CONNECTED_NORMALLY:
     case CONNECTION_RECONFIGURATION:
     case CONNECTION_REESTABLISHMENT:
     case HANDOVER_PREPARATION:
@@ -646,27 +648,27 @@
         pdcpSapProvider->TransmitPdcpSdu (params);
       }
       break;
-      
+
     case HANDOVER_LEAVING:
       {
         NS_LOG_LOGIC ("forwarding data to target eNB over X2-U");
-        uint8_t drbid = Bid2Drbid (bid);        
+        uint8_t drbid = Bid2Drbid (bid);
         EpcX2Sap::UeDataParams params;
         params.sourceCellId = m_rrc->m_cellId;
         params.targetCellId = m_targetCellId;
         params.gtpTeid = GetDataRadioBearerInfo (drbid)->m_gtpTeid;
         params.ueData = p;
         m_rrc->m_x2SapProvider->SendUeData (params);
-      }      
+      }
       break;
-      
+
     default:
       NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
-      break;      
+      break;
     }
 }
 
-std::vector<EpcX2Sap::ErabToBeSetupItem>   
+std::vector<EpcX2Sap::ErabToBeSetupItem>
 UeManager::GetErabList ()
 {
   NS_LOG_FUNCTION (this);
@@ -681,7 +683,7 @@
       etbsi.dlForwarding = false;
       etbsi.transportLayerAddress = it->second->m_transportLayerAddress;
       etbsi.gtpTeid = it->second->m_gtpTeid;
-      ret.push_back (etbsi);      
+      ret.push_back (etbsi);
     }
   return ret;
 }
@@ -691,7 +693,7 @@
 {
   NS_LOG_FUNCTION (this);
   switch (m_state)
-    {     
+    {
     case HANDOVER_PATH_SWITCH:
       NS_LOG_INFO ("Send UE CONTEXT RELEASE from target eNB to source eNB");
       EpcX2SapProvider::UeContextReleaseParams ueCtxReleaseParams;
@@ -702,10 +704,10 @@
       SwitchToState (CONNECTED_NORMALLY);
       m_rrc->m_handoverEndOkTrace (m_imsi, m_rrc->m_cellId, m_rnti);
       break;
-      
+
     default:
       NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
-      break;      
+      break;
     }
 }
 
@@ -714,16 +716,16 @@
 {
   NS_LOG_FUNCTION (this << cellId);
   switch (m_state)
-    {     
-    case HANDOVER_PREPARATION:   
+    {
+    case HANDOVER_PREPARATION:
       NS_ASSERT (cellId == m_targetCellId);
       NS_LOG_INFO ("target eNB sent HO preparation failure, aborting HO");
       SwitchToState (CONNECTED_NORMALLY);
       break;
-      
+
     default:
       NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
-      break;      
+      break;
     }
 }
 
@@ -751,7 +753,7 @@
 {
   NS_LOG_FUNCTION (this);
   NS_ASSERT_MSG (m_state == HANDOVER_LEAVING, "method unexpected in state " << ToString (m_state));
-  m_handoverLeavingTimeout.Cancel ();  
+  m_handoverLeavingTimeout.Cancel ();
 }
 
 
@@ -845,27 +847,30 @@
     {
     case CONNECTION_RECONFIGURATION:
       StartDataRadioBearers ();
-      if (m_needTransmissionModeConfiguration)
+      if (m_needPhyMacConfiguration)
         {
           // configure MAC (and scheduler)
           LteEnbCmacSapProvider::UeConfig req;
           req.m_rnti = m_rnti;
           req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
-          m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);  
-          
+          m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
+
           // configure PHY
           m_rrc->m_cphySapProvider->SetTransmissionMode (req.m_rnti, req.m_transmissionMode);
-          
-          m_needTransmissionModeConfiguration = false;
+
+          double paDouble = LteRrcSap::ConvertPdschConfigDedicated2Double (m_physicalConfigDedicated.pdschConfigDedicated);
+          m_rrc->m_cphySapProvider->SetPa (m_rnti, paDouble);
+
+          m_needPhyMacConfiguration = false;
         }
       SwitchToState (CONNECTED_NORMALLY);
       m_rrc->m_connectionReconfigurationTrace (m_imsi, m_rrc->m_cellId, m_rnti);
       break;
 
-    case HANDOVER_LEAVING:      
+    case HANDOVER_LEAVING:
       NS_LOG_INFO ("ignoring RecvRrcConnectionReconfigurationCompleted in state " << ToString (m_state));
       break;
-      
+
     case HANDOVER_JOINING:
       {
         m_handoverJoiningTimeout.Cancel ();
@@ -883,17 +888,17 @@
             b.epsBearerId = it->second->m_epsBearerIdentity;
             b.teid =  it->second->m_gtpTeid;
             params.bearersToBeSwitched.push_back (b);
-          }     
+          }
         m_rrc->m_s1SapProvider->PathSwitchRequest (params);
       }
       break;
-      
+
     default:
       NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
-      break;      
+      break;
     }
 }
-  
+
 void 
 UeManager::RecvRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg)
 {
@@ -903,13 +908,13 @@
     case CONNECTED_NORMALLY:
       break;
 
-    case HANDOVER_LEAVING:      
-      m_handoverLeavingTimeout.Cancel ();  
-      break;      
-      
+    case HANDOVER_LEAVING:
+      m_handoverLeavingTimeout.Cancel ();
+      break;
+
     default:
       NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
-      break;      
+      break;
     }
 
   LteRrcSap::RrcConnectionReestablishment msg2;
@@ -932,19 +937,19 @@
   uint8_t measId = msg.measResults.measId;
   NS_LOG_FUNCTION (this << (uint16_t) measId);
   NS_LOG_LOGIC ("measId " << (uint16_t) measId
-                << " haveMeasResultNeighCells " << msg.measResults.haveMeasResultNeighCells
-                << " measResultListEutra " << msg.measResults.measResultListEutra.size ());
+                          << " haveMeasResultNeighCells " << msg.measResults.haveMeasResultNeighCells
+                          << " measResultListEutra " << msg.measResults.measResultListEutra.size ());
   NS_LOG_LOGIC ("serving cellId " << m_rrc->m_cellId
-                << " RSRP " << (uint16_t) msg.measResults.rsrpResult
-                << " RSRQ " << (uint16_t) msg.measResults.rsrqResult);
+                                  << " RSRP " << (uint16_t) msg.measResults.rsrpResult
+                                  << " RSRQ " << (uint16_t) msg.measResults.rsrqResult);
 
   for (std::list <LteRrcSap::MeasResultEutra>::iterator it = msg.measResults.measResultListEutra.begin ();
        it != msg.measResults.measResultListEutra.end ();
        ++it)
     {
       NS_LOG_LOGIC ("neighbour cellId " << it->physCellId
-                    << " RSRP " << (it->haveRsrpResult ? (uint16_t) it->rsrpResult : 255)
-                    << " RSRQ " << (it->haveRsrqResult ? (uint16_t) it->rsrqResult : 255));
+                                        << " RSRP " << (it->haveRsrpResult ? (uint16_t) it->rsrpResult : 255)
+                                        << " RSRQ " << (it->haveRsrqResult ? (uint16_t) it->rsrqResult : 255));
     }
 
   if ((m_rrc->m_handoverManagementSapProvider != 0)
@@ -962,6 +967,13 @@
       m_rrc->m_anrSapProvider->ReportUeMeas (msg.measResults);
     }
 
+  if ((m_rrc->m_ffrRrcSapProvider != 0)
+      && (m_rrc->m_ffrMeasIds.find (measId) != m_rrc->m_ffrMeasIds.end ()))
+    {
+      // this measurement was requested by the FFR function
+      m_rrc->m_ffrRrcSapProvider->ReportUeMeas (m_rnti, msg.measResults);
+    }
+
   // fire a trace source
   m_rrc->m_recvMeasurementReportTrace (m_imsi, m_rrc->m_cellId, m_rnti, msg);
 
@@ -975,10 +987,10 @@
 {
   NS_LOG_FUNCTION (this << m_rnti);
   // at this stage used only by the scheduler for updating txMode
-  
+
   m_physicalConfigDedicated.antennaInfo.transmissionMode = cmacParams.m_transmissionMode;
 
-  m_needTransmissionModeConfiguration = true;
+  m_needPhyMacConfiguration = true;
 
   // reconfigure the UE RRC
   ScheduleRrcConnectionReconfiguration ();
@@ -1033,7 +1045,7 @@
       // do nothing, srs conf index will be correctly enforced upon
       // RRC connection establishment
       break;
-      
+
     default:
       ScheduleRrcConnectionReconfiguration ();
       break;
@@ -1046,11 +1058,23 @@
   return m_state;
 }
 
+void
+UeManager::SetPdschConfigDedicated (LteRrcSap::PdschConfigDedicated pdschConfigDedicated)
+{
+  NS_LOG_FUNCTION (this);
+  m_physicalConfigDedicated.pdschConfigDedicated = pdschConfigDedicated;
+
+  m_needPhyMacConfiguration = true;
+
+  // reconfigure the UE RRC
+  ScheduleRrcConnectionReconfiguration ();
+}
+
 uint8_t
 UeManager::AddDataRadioBearerInfo (Ptr<LteDataRadioBearerInfo> drbInfo)
 {
   NS_LOG_FUNCTION (this);
-  const uint8_t MAX_DRB_ID = 32;  
+  const uint8_t MAX_DRB_ID = 32;
   for (int drbid = (m_lastAllocatedDrbid + 1) % MAX_DRB_ID; 
        drbid != m_lastAllocatedDrbid; 
        drbid = (drbid + 1) % MAX_DRB_ID)
@@ -1075,7 +1099,7 @@
 {
   NS_LOG_FUNCTION (this << (uint32_t) drbid);
   NS_ASSERT (0 != drbid);
-  std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);  
+  std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
   NS_ABORT_IF (it == m_drbMap.end ());
   return it->second;
 }
@@ -1117,7 +1141,7 @@
       stam.logicalChannelConfig = m_srb1->m_logicalChannelConfig;
       rrcd.srbToAddModList.push_back (stam);
     }
-    
+
   for (std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.begin ();
        it != m_drbMap.end ();
        ++it)
@@ -1189,18 +1213,18 @@
   NS_LOG_INFO (this << " IMSI " << m_imsi << " RNTI " << m_rnti << " UeManager "
                     << ToString (oldState) << " --> " << ToString (newState));
   m_stateTransitionTrace (m_imsi, m_rrc->m_cellId, m_rnti, oldState, newState);
-  
+
   switch (newState)
     {
     case INITIAL_RANDOM_ACCESS:
     case HANDOVER_JOINING:
-      NS_FATAL_ERROR ("cannot switch to an initial state");      
+      NS_FATAL_ERROR ("cannot switch to an initial state");
       break;
 
     case CONNECTION_SETUP:
       break;
 
-    case CONNECTED_NORMALLY:    
+    case CONNECTED_NORMALLY:
       {
         if (m_pendingRrcConnectionReconfiguration == true)
           {
@@ -1214,9 +1238,9 @@
 
     case CONNECTION_REESTABLISHMENT:
       break;
-      
+
     case HANDOVER_LEAVING:
-      break;      
+      break;
 
     default:
       break;
@@ -1236,6 +1260,7 @@
     m_cmacSapProvider (0),
     m_handoverManagementSapProvider (0),
     m_anrSapProvider (0),
+    m_ffrRrcSapProvider (0),
     m_rrcSapUser (0),
     m_macSapProvider (0),
     m_s1SapProvider (0),
@@ -1250,6 +1275,7 @@
   m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this);
   m_handoverManagementSapUser = new MemberLteHandoverManagementSapUser<LteEnbRrc> (this);
   m_anrSapUser = new MemberLteAnrSapUser<LteEnbRrc> (this);
+  m_ffrRrcSapUser = new MemberLteFfrRrcSapUser<LteEnbRrc> (this);
   m_rrcSapProvider = new MemberLteEnbRrcSapProvider<LteEnbRrc> (this);
   m_x2SapUser = new EpcX2SpecificEpcX2SapUser<LteEnbRrc> (this);
   m_s1SapUser = new MemberEpcEnbS1SapUser<LteEnbRrc> (this);
@@ -1271,6 +1297,7 @@
   delete m_cmacSapUser;
   delete m_handoverManagementSapUser;
   delete m_anrSapUser;
+  delete m_ffrRrcSapUser;
   delete m_rrcSapProvider;
   delete m_x2SapUser;
   delete m_s1SapUser;
@@ -1358,18 +1385,18 @@
                    MakeTimeChecker ())
 
     // Cell selection related attribute
-   .AddAttribute ("QRxLevMin",
-                  "One of information transmitted within the SIB1 message, "
-                  "indicating the required minimum RSRP level that any UE must "
-                  "receive from this cell before it is allowed to camp to this "
-                  "cell. The default value -70 corresponds to -140 dBm and is "
-                  "the lowest possible value as defined by Section 6.3.4 of "
-                  "3GPP TS 36.133. This restriction, however, only applies to "
-                  "initial cell selection and EPC-enabled simulation.",
-                  TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
-                  IntegerValue (-70),
-                  MakeIntegerAccessor (&LteEnbRrc::m_qRxLevMin),
-                  MakeIntegerChecker<int8_t> (-70, -22))
+    .AddAttribute ("QRxLevMin",
+                   "One of information transmitted within the SIB1 message, "
+                   "indicating the required minimum RSRP level that any UE must "
+                   "receive from this cell before it is allowed to camp to this "
+                   "cell. The default value -70 corresponds to -140 dBm and is "
+                   "the lowest possible value as defined by Section 6.3.4 of "
+                   "3GPP TS 36.133. This restriction, however, only applies to "
+                   "initial cell selection and EPC-enabled simulation.",
+                   TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
+                   IntegerValue (-70),
+                   MakeIntegerAccessor (&LteEnbRrc::m_qRxLevMin),
+                   MakeIntegerChecker<int8_t> (-70, -22))
 
     // Handover related attributes
     .AddAttribute ("AdmitHandoverRequest",
@@ -1481,6 +1508,20 @@
 }
 
 void
+LteEnbRrc::SetLteFfrRrcSapProvider (LteFfrRrcSapProvider * s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapProvider = s;
+}
+
+LteFfrRrcSapUser*
+LteEnbRrc::GetLteFfrRrcSapUser ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapUser;
+}
+
+void
 LteEnbRrc::SetLteEnbRrcSapUser (LteEnbRrcSapUser * s)
 {
   NS_LOG_FUNCTION (this << s);
@@ -1507,7 +1548,7 @@
   m_s1SapProvider = s;
 }
 
-  
+
 EpcEnbS1SapUser* 
 LteEnbRrc::GetS1SapUser ()
 {
@@ -1650,6 +1691,8 @@
   m_ulBandwidth = ulBandwidth;
   m_cellId = cellId;
   m_cphySapProvider->SetCellId (cellId);
+  m_ffrRrcSapProvider->SetCellId (cellId);
+  m_ffrRrcSapProvider->SetBandwidth(ulBandwidth, dlBandwidth);
 
   /*
    * Initializing the list of UE measurement configuration (m_ueMeasConfig).
@@ -1815,12 +1858,12 @@
   NS_LOG_FUNCTION (this << rnti);
   GetUeManager (rnti)->RecvRrcConnectionReconfigurationCompleted (msg);
 }
-  
+
 void 
 LteEnbRrc::DoRecvRrcConnectionReestablishmentRequest (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentRequest msg)
 {
   NS_LOG_FUNCTION (this << rnti);
-  GetUeManager (rnti)->RecvRrcConnectionReestablishmentRequest (msg);  
+  GetUeManager (rnti)->RecvRrcConnectionReestablishmentRequest (msg);
 }
 
 void 
@@ -1841,7 +1884,7 @@
 LteEnbRrc::DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters request)
 {
   Ptr<UeManager> ueManager = GetUeManager (request.rnti);
-  ueManager->SetupDataRadioBearer (request.bearer, request.bearerId, request.gtpTeid, request.transportLayerAddress);       
+  ueManager->SetupDataRadioBearer (request.bearer, request.bearerId, request.gtpTeid, request.transportLayerAddress);
 }
 
 void 
@@ -1870,14 +1913,14 @@
       NS_LOG_INFO ("rejecting handover request from cellId " << req.sourceCellId);
       EpcX2Sap::HandoverPreparationFailureParams res;
       res.oldEnbUeX2apId =  req.oldEnbUeX2apId;
-      res.sourceCellId = req.sourceCellId ;
-      res.targetCellId = req.targetCellId ;
+      res.sourceCellId = req.sourceCellId;
+      res.targetCellId = req.targetCellId;
       res.cause = 0;
       res.criticalityDiagnostics = 0;
       m_x2SapProvider->SendHandoverPreparationFailure (res);
       return;
     }
-  
+
   uint16_t rnti = AddUe (UeManager::HANDOVER_JOINING);
   LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue anrcrv = m_cmacSapProvider->AllocateNcRaPreamble (rnti);
   if (anrcrv.valid == false)
@@ -1886,7 +1929,7 @@
       RemoveUe (rnti);
       NS_FATAL_ERROR ("should trigger HO Preparation Failure, but it is not implemented");
       return;
-    }    
+    }
 
   Ptr<UeManager> ueManager = GetUeManager (rnti);
   ueManager->SetSource (req.sourceCellId, req.oldEnbUeX2apId);
@@ -1945,16 +1988,16 @@
 LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params)
 {
   NS_LOG_FUNCTION (this);
-  
+
   NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK");
-  
+
   NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
   NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
   NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
   NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
 
   uint16_t rnti = params.oldEnbUeX2apId;
-  Ptr<UeManager> ueManager = GetUeManager (rnti);  
+  Ptr<UeManager> ueManager = GetUeManager (rnti);
   ueManager->RecvHandoverRequestAck (params);
 }
 
@@ -2016,7 +2059,7 @@
 
   NS_LOG_LOGIC ("Number of cellInformationItems = " << params.cellInformationList.size ());
 
-  NS_ASSERT ("Processing of LOAD INFORMATION X2 message IS NOT IMPLEMENTED");
+  m_ffrRrcSapProvider->RecvLoadInformation(params);
 }
 
 void
@@ -2045,7 +2088,7 @@
 
   std::map<uint32_t, X2uTeidInfo>::iterator 
     teidInfoIt = m_x2uTeidInfoMap.find (params.gtpTeid);
-  if (teidInfoIt != m_x2uTeidInfoMap.end ())    
+  if (teidInfoIt != m_x2uTeidInfoMap.end ())
     {
       GetUeManager (teidInfoIt->second.rnti)->SendData (teidInfoIt->second.drbid, params.ueData);
     }
@@ -2138,7 +2181,30 @@
   return measId;
 }
 
+uint8_t
+LteEnbRrc::DoAddUeMeasReportConfigForFfr (LteRrcSap::ReportConfigEutra reportConfig)
+{
+  NS_LOG_FUNCTION (this);
+  uint8_t measId = AddUeMeasReportConfig (reportConfig);
+  m_ffrMeasIds.insert (measId);
+  return measId;
+}
 
+void
+LteEnbRrc::DoSetPdschConfigDedicated (uint16_t rnti, LteRrcSap::PdschConfigDedicated pdschConfigDedicated)
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<UeManager> ueManager = GetUeManager (rnti);
+  ueManager->SetPdschConfigDedicated (pdschConfigDedicated);
+}
+
+void
+LteEnbRrc::DoSendLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_x2SapProvider->SendLoadInformation(params);
+}
 
 uint16_t
 LteEnbRrc::AddUe (UeManager::State state)
@@ -2162,8 +2228,8 @@
   Ptr<UeManager> ueManager = CreateObject<UeManager> (this, rnti, state);
   m_ueMap.insert (std::pair<uint16_t, Ptr<UeManager> > (rnti, ueManager));
   ueManager->Initialize ();
-  NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueManager->GetSrsConfigurationIndex ());      
-  m_newUeContextTrace (m_cellId, rnti);      
+  NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueManager->GetSrsConfigurationIndex ());
+  m_newUeContextTrace (m_cellId, rnti);
   return rnti;
 }
 
@@ -2289,9 +2355,9 @@
   if (m_ueSrsConfigurationIndexSet.size () >= g_srsPeriodicity[m_srsCurrentPeriodicityId])
     {
       NS_FATAL_ERROR ("too many UEs (" << m_ueSrsConfigurationIndexSet.size () + 1 
-                      << ") for current SRS periodicity " 
-                      <<  g_srsPeriodicity[m_srsCurrentPeriodicityId]
-                      << ", consider increasing the value of ns3::LteEnbRrc::SrsPeriodicity");
+                                       << ") for current SRS periodicity "
+                                       <<  g_srsPeriodicity[m_srsCurrentPeriodicityId]
+                                       << ", consider increasing the value of ns3::LteEnbRrc::SrsPeriodicity");
     }
 
   if (m_ueSrsConfigurationIndexSet.empty ())
@@ -2328,7 +2394,7 @@
         } 
     }
   return m_lastAllocatedConfigurationIndex;
-  
+
 }
 
 
@@ -2373,6 +2439,8 @@
   si.haveSib2 = true;
   si.sib2.freqInfo.ulCarrierFreq = m_ulEarfcn;
   si.sib2.freqInfo.ulBandwidth = m_ulBandwidth;
+  si.sib2.radioResourceConfigCommon.pdschConfigCommon.referenceSignalPower = m_cphySapProvider->GetReferenceSignalPower();
+  si.sib2.radioResourceConfigCommon.pdschConfigCommon.pb = 0;
 
   LteEnbCmacSapProvider::RachConfig rc = m_cmacSapProvider->GetRachConfig ();
   LteRrcSap::RachConfigCommon rachConfigCommon;
--- a/src/lte/model/lte-enb-rrc.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-enb-rrc.h	Fri Sep 05 01:12:55 2014 +0200
@@ -39,6 +39,7 @@
 #include <ns3/lte-enb-cphy-sap.h>
 #include <ns3/lte-rrc-sap.h>
 #include <ns3/lte-anr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
 
 #include <map>
 #include <set>
@@ -139,7 +140,7 @@
    * 
    */
   void RecordDataRadioBearersToBeStarted ();
-  
+
   /** 
    * Start the data radio bearers that have been previously recorded
    * to be started using RecordDataRadioBearersToBeStarted() 
@@ -174,7 +175,7 @@
    * \param params 
    */
   void RecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params);
-  
+
   /** 
    * 
    * \return the HandoverPreparationInfo sent by the source eNB to the
@@ -261,7 +262,7 @@
   // METHODS FORWARDED FROM ENB PDCP SAP //////////////////////////////////////
 
   void DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params);
-  
+
   /** 
    * 
    * \return the RNTI, i.e., an UE identifier that is unique within
@@ -294,6 +295,13 @@
    */
   State GetState () const;
 
+  /**
+   * Configure PdschConfigDedicated (i.e. P_A value) for UE and start RrcConnectionReconfiguration
+   * to inform UE about new PdschConfigDedicated
+   *
+   * \param pdschConfigDedicated new pdschConfigDedicated (i.e. P_A value) to be set
+   */
+  void SetPdschConfigDedicated (LteRrcSap::PdschConfigDedicated pdschConfigDedicated);
 
 private:
 
@@ -381,7 +389,7 @@
    * \return the corresponding Data Radio Bearer Id
    */
   uint8_t Bid2Drbid (uint8_t bid);
-  
+
   /** 
    * Switch the UeManager to the given state
    * 
@@ -408,7 +416,7 @@
   uint16_t m_sourceCellId;
   uint16_t m_targetCellId;
   std::list<uint8_t> m_drbsToBeStarted;
-  bool m_needTransmissionModeConfiguration;
+  bool m_needPhyMacConfiguration;
 
   EventId m_connectionRequestTimeout;
   EventId m_connectionSetupTimeout;
@@ -431,6 +439,7 @@
   friend class EnbRrcMemberLteEnbCmacSapUser;
   friend class MemberLteHandoverManagementSapUser<LteEnbRrc>;
   friend class MemberLteAnrSapUser<LteEnbRrc>;
+  friend class MemberLteFfrRrcSapUser<LteEnbRrc>;
   friend class MemberLteEnbRrcSapProvider<LteEnbRrc>;
   friend class MemberEpcEnbS1SapUser<LteEnbRrc>;
   friend class EpcX2SpecificEpcX2SapUser<LteEnbRrc>;
@@ -513,6 +522,21 @@
   LteAnrSapUser* GetLteAnrSapUser ();
 
 
+
+  /**
+   * set the FFR SAP this RRC should interact with
+   *
+   * \param s the FFR SAP Provider to be used by this RRC
+   */
+  void SetLteFfrRrcSapProvider (LteFfrRrcSapProvider * s);
+
+  /**
+   * Get the FFR SAP offered by this RRC
+   * \return s the FFR SAP User interface offered to the ANR instance by this
+   *           RRC
+   */
+  LteFfrRrcSapUser* GetLteFfrRrcSapUser ();
+
   /**
    * set the RRC SAP this RRC should interact with
    *
@@ -764,6 +788,10 @@
 
   uint8_t DoAddUeMeasReportConfigForAnr (LteRrcSap::ReportConfigEutra reportConfig);
 
+  // FFR RRC SAP methods
+  uint8_t DoAddUeMeasReportConfigForFfr (LteRrcSap::ReportConfigEutra reportConfig);
+  void DoSetPdschConfigDedicated (uint16_t rnti, LteRrcSap::PdschConfigDedicated pa);
+  void DoSendLoadInformation (EpcX2Sap::LoadInformationParams params);
 
   // Internal methods
 
@@ -902,6 +930,9 @@
   LteAnrSapUser* m_anrSapUser;
   LteAnrSapProvider* m_anrSapProvider;
 
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
   LteEnbRrcSapUser* m_rrcSapUser;
   LteEnbRrcSapProvider* m_rrcSapProvider;
 
@@ -934,6 +965,7 @@
 
   std::set<uint8_t> m_handoverMeasIds;
   std::set<uint8_t> m_anrMeasIds;
+  std::set<uint8_t> m_ffrMeasIds;
 
   struct X2uTeidInfo
   {
@@ -974,15 +1006,15 @@
   Time m_handoverJoiningTimeoutDuration;
   Time m_handoverLeavingTimeoutDuration;
 
-  //             cellid    rnti   
+  //             cellid    rnti
   TracedCallback<uint16_t, uint16_t> m_newUeContextTrace;
-  //             imsi      cellid    rnti   
+  //             imsi      cellid    rnti
   TracedCallback<uint64_t, uint16_t, uint16_t> m_connectionEstablishedTrace;
-  //             imsi      cellid    rnti   
+  //             imsi      cellid    rnti
   TracedCallback<uint64_t, uint16_t, uint16_t> m_connectionReconfigurationTrace;
   //             imsi      cellid    rnti     targetCellId
   TracedCallback<uint64_t, uint16_t, uint16_t, uint16_t> m_handoverStartTrace;
-  //             imsi      cellid    rnti    
+  //             imsi      cellid    rnti
   TracedCallback<uint64_t, uint16_t, uint16_t> m_handoverEndOkTrace;
 
   //             imsi      cellid    rnti
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-algorithm.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,180 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-ffr-algorithm.h"
+#include "ns3/uinteger.h"
+#include "ns3/boolean.h"
+#include <ns3/log.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteFfrAlgorithm");
+
+namespace ns3 {
+
+static const int Type0AllocationRbg[4] = {
+  10,       // RGB size 1
+  26,       // RGB size 2
+  63,       // RGB size 3
+  110       // RGB size 4
+};  // see table 7.1.6.1-1 of 3GPP TS 36.213
+
+NS_OBJECT_ENSURE_REGISTERED (LteFfrAlgorithm);
+
+
+LteFfrAlgorithm::LteFfrAlgorithm () :
+  m_needReconfiguration (true)
+{
+}
+
+
+LteFfrAlgorithm::~LteFfrAlgorithm ()
+{
+}
+
+
+TypeId
+LteFfrAlgorithm::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFfrAlgorithm")
+    .SetParent<Object> ()
+    .AddAttribute ("FrCellTypeId",
+                   "Downlink FR cell type ID for automatic configuration,"
+                   "default value is 0 and it means that user needs to configure FR algorithm manually,"
+                   "if it is set to 1,2 or 3 FR algorithm will be configured automatically",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFfrAlgorithm::SetFrCellTypeId,&LteFfrAlgorithm::GetFrCellTypeId),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EnabledInUplink",
+                   "If FR algorithm will also work in Uplink, default value true",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&LteFfrAlgorithm::m_enabledInUplink),
+                   MakeBooleanChecker ())
+  ;
+  return tid;
+}
+
+
+void
+LteFfrAlgorithm::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+uint8_t
+LteFfrAlgorithm::GetUlBandwidth () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_ulBandwidth;
+}
+
+void
+LteFfrAlgorithm::SetUlBandwidth (uint8_t bw)
+{
+  NS_LOG_FUNCTION (this << uint16_t (bw));
+  switch (bw)
+    {
+    case 6:
+    case 15:
+    case 25:
+    case 50:
+    case 75:
+    case 100:
+      m_ulBandwidth = bw;
+      break;
+
+    default:
+      NS_FATAL_ERROR ("invalid bandwidth value " << (uint16_t) bw);
+      break;
+    }
+}
+
+uint8_t
+LteFfrAlgorithm::GetDlBandwidth () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_dlBandwidth;
+}
+
+void
+LteFfrAlgorithm::SetDlBandwidth (uint8_t bw)
+{
+  NS_LOG_FUNCTION (this << uint16_t (bw));
+  switch (bw)
+    {
+    case 6:
+    case 15:
+    case 25:
+    case 50:
+    case 75:
+    case 100:
+      m_dlBandwidth = bw;
+      break;
+
+    default:
+      NS_FATAL_ERROR ("invalid bandwidth value " << (uint16_t) bw);
+      break;
+    }
+}
+
+void
+LteFfrAlgorithm::SetFrCellTypeId (uint8_t cellTypeId)
+{
+  NS_LOG_FUNCTION (this << uint16_t (cellTypeId));
+  m_frCellTypeId = cellTypeId;
+  m_needReconfiguration = true;
+}
+
+uint8_t
+LteFfrAlgorithm::GetFrCellTypeId () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_frCellTypeId;
+}
+
+int
+LteFfrAlgorithm::GetRbgSize (int dlbandwidth)
+{
+  for (int i = 0; i < 4; i++)
+    {
+      if (dlbandwidth < Type0AllocationRbg[i])
+        {
+          return (i + 1);
+        }
+    }
+
+  return (-1);
+}
+
+void
+LteFfrAlgorithm::DoSetCellId (uint16_t cellId )
+{
+  NS_LOG_FUNCTION (this);
+  m_cellId = cellId;
+}
+
+void
+LteFfrAlgorithm::DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  SetDlBandwidth (dlBandwidth);
+  SetUlBandwidth (ulBandwidth);
+}
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-algorithm.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,259 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FFR_ALGORITHM_H
+#define LTE_FFR_ALGORITHM_H
+
+#include <ns3/object.h>
+#include <ns3/lte-rrc-sap.h>
+#include <ns3/epc-x2-sap.h>
+#include <ns3/ff-mac-sched-sap.h>
+#include <map>
+
+namespace ns3 {
+
+class LteFfrSapUser;
+class LteFfrSapProvider;
+
+class LteFfrRrcSapUser;
+class LteFfrRrcSapProvider;
+
+/**
+ * \brief The abstract base class of a Frequency Reuse algorithm
+ *
+ * Generally Frequency reuse algorithm tells the Scheduler which RB can be allocated
+ * and which can not. FR policy depend on its implementation.
+ *
+ * The communication with the eNodeB MAC Scheduler instance is done through
+ * the *LteFfrSap* interface. The frequency reuse algorithm instance corresponds to the
+ * "provider" part of this interface, while the eNodeB MAC Scheduler instance takes the
+ * role of the "user" part.
+ *
+ * The communication with the eNodeB RRC instance is done through the *LteFfrRrcSap*
+ * interface. The frequency reuse algorithm instance corresponds to the
+ * "provider" part of this interface, while the eNodeB RRC instance takes the
+ * role of the "user" part.
+ *
+ */
+
+class LteFfrAlgorithm : public Object
+{
+public:
+  LteFfrAlgorithm ();
+  virtual ~LteFfrAlgorithm ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  /**
+   * \brief Set the "user" part of the LteFfrSap interface that
+   *        this frequency reuse algorithm instance will interact with.
+   * \param s a reference to the "user" part of the interface, typically a
+   *          member of an Scheduler instance
+   */
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s) = 0;
+
+  /**
+   * \brief Set the "user" part of the LteFfrRrcSap interface that
+   *        this frequency reuse algorithm instance will interact with.
+   * \param s a reference to the "user" part of the interface, typically a
+   *          member of an LteEnbRrc instance
+   */
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s) = 0;
+
+  /**
+   * \brief Export the "provider" part of the LteFfrSap interface.
+   * \return the reference to the "provider" part of the interface, typically to
+   *         be kept by an Scheduler instance
+   */
+  virtual LteFfrSapProvider* GetLteFfrSapProvider () = 0;
+
+  /**
+   * \brief Export the "provider" part of the LteFfrRrcSap interface.
+   * \return the reference to the "provider" part of the interface, typically to
+   *         be kept by an LteEnbRrc instance
+   */
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider () = 0;
+
+  /**
+   * \return the uplink bandwidth in RBs
+   */
+  uint8_t GetUlBandwidth () const;
+
+  /**
+   * \param bw the uplink bandwidth in RBs
+   */
+  void SetUlBandwidth (uint8_t bw);
+
+  /**
+   * \return the downlink bandwidth in RBs
+   */
+  uint8_t GetDlBandwidth () const;
+
+  /**
+   * \param bw the downlink bandwidth in RBs
+   */
+  void SetDlBandwidth (uint8_t bw);
+
+  /**
+   * \param cellTypeId for automatic FR configuration
+   */
+  void SetFrCellTypeId (uint8_t cellTypeId);
+
+  /**
+   * \return cellTypeId which is used for automatic FR configuration
+   */
+  uint8_t GetFrCellTypeId () const;
+
+protected:
+
+  // inherited from Object
+  virtual void DoDispose ();
+
+  /**
+   * \brief Automatic FR reconfiguration
+   */
+  virtual void Reconfigure () = 0;
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+
+  /**
+   * \brief Implementation of LteFfrSapProvider::GetAvailableDlRbg
+   * \return vector of size (m_dlBandwidth/RbgSize); false indicates
+   *                    that RBG is free to use, true otherwise
+   */
+  virtual std::vector <bool> DoGetAvailableDlRbg () = 0;
+
+  /**
+   * \brief Implementation of LteFfrSapProvider::IsDlRbgAvailableForUe
+   * \param rbId
+   * \param rnti Radio Network Temporary Identity, an integer identifying the UE
+   *             where the report originates from
+   * \return true if UE can be served on i-th RB, false otherwise
+   */
+  virtual bool DoIsDlRbgAvailableForUe (int rbId, uint16_t rnti) = 0;
+
+  /**
+   * \brief Implementation of LteFfrSapProvider::GetAvailableUlRbg.
+   * \return vector of size m_ulBandwidth; false indicates
+   *                    that RB is free to use, true otherwise
+   */
+  virtual std::vector <bool> DoGetAvailableUlRbg () = 0;
+
+  /**
+   * \brief Implementation of LteFfrSapProvider::IsUlRbgAvailableForUe.
+   * \param rbId
+   * \param rnti Radio Network Temporary Identity, an integer identifying the UE
+   *             where the report originates from
+   * \return true if UE can be served on i-th RB, false otherwise
+   */
+  virtual bool DoIsUlRbgAvailableForUe (int rbId, uint16_t rnti) = 0;
+
+  /**
+   * \brief DoReportDlCqiInfo
+   * \param params
+   *
+   */
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params) = 0;
+
+  /**
+   * \brief DoReportUlCqiInfo
+   * \param params
+   *
+   */
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params) = 0;
+
+  /**
+   * \brief DoReportUlCqiInfo
+   * \param ulCqiMap
+   *
+   */
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap ) = 0;
+
+  /**
+   * \brief DoGetTpc for UE
+   * \param rnti
+   * \return TPC value
+   */
+  virtual uint8_t DoGetTpc (uint16_t rnti) = 0;
+
+  /**
+   * \brief DoGetMinContinuousUlBandwidth in number of RB
+   * \return number of RB in min continous UL Bandwidth
+   */
+  virtual uint8_t DoGetMinContinuousUlBandwidth () = 0;
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+
+  /**
+   * \brief SetCellId
+   * \param cellId the Cell Identifier
+   */
+  virtual void DoSetCellId (uint16_t cellId);
+
+  /**
+   * \brief Implementation of LteFfrRrcSapProvider::SetBandwidth.
+   * \param ulBandwidth UL bandwidth in number of RB
+   * \param dlBandwidth DL bandwidth in number of RB
+   */
+  virtual void DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
+
+  /**
+   * \brief Implementation of LteFfrRrcSapProvider::ReportUeMeas.
+   * \param rnti Radio Network Temporary Identity, an integer identifying the UE
+   *             where the report originates from
+   * \param measResults a single report of one measurement identity
+   */
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults) = 0;
+
+  /**
+   * \brief DoRecvLoadInformation
+   * \param params
+   *
+   */
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params) = 0;
+
+  /**
+  * \brief Get RBG size for DL Bandwidth according to table 7.1.6.1-1 of 36.213
+  * \param dlbandwidth
+  * \return size of RBG in number of RB
+  */
+  int GetRbgSize (int dlbandwidth);
+
+
+  uint16_t m_cellId;
+
+  uint8_t m_dlBandwidth; /**< downlink bandwidth in RBs */
+  uint8_t m_ulBandwidth; /**< uplink bandwidth in RBs */
+
+  uint8_t m_frCellTypeId; /**< FFR cell type ID for automatic configuration */
+
+  bool m_enabledInUplink; /**< If true FR algorithm will also work in Uplink*/
+
+  bool m_needReconfiguration; /**< If true FR algorithm will be reconfigured*/
+
+}; // end of class LteFfrAlgorithm
+
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FFR_ALGORITHM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-distributed-algorithm.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,711 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-ffr-distributed-algorithm.h"
+#include <ns3/log.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteFfrDistributedAlgorithm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteFfrDistributedAlgorithm);
+
+
+LteFfrDistributedAlgorithm::LteFfrDistributedAlgorithm ()
+  : m_ffrSapUser (0),
+    m_ffrRrcSapUser (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_ffrSapProvider = new MemberLteFfrSapProvider<LteFfrDistributedAlgorithm> (this);
+  m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFfrDistributedAlgorithm> (this);
+}
+
+
+LteFfrDistributedAlgorithm::~LteFfrDistributedAlgorithm ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteFfrDistributedAlgorithm::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ffrSapProvider;
+  delete m_ffrRrcSapProvider;
+}
+
+
+TypeId
+LteFfrDistributedAlgorithm::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFfrDistributedAlgorithm")
+    .SetParent<LteFfrAlgorithm> ()
+    .AddConstructor<LteFfrDistributedAlgorithm> ()
+    .AddAttribute ("CalculationInterval",
+                   "Time interval between calculation of Edge sub-band, Default value 1 second",
+                   TimeValue (Seconds (1)),
+                   MakeTimeAccessor (&LteFfrDistributedAlgorithm::m_calculationInterval),
+                   MakeTimeChecker ())
+    .AddAttribute ("RsrqThreshold",
+                   "If the RSRQ of is worse than this threshold, UE should be served in Edge sub-band",
+                   UintegerValue (20),
+                   MakeUintegerAccessor (&LteFfrDistributedAlgorithm::m_egdeSubBandRsrqThreshold),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("RsrpDifferenceThreshold",
+                   "If the difference between the power of the signal received by UE from "
+                   "the serving cell and the power of the signal received from the adjacent cell is less "
+                   "than a RsrpDifferenceThreshold value, the cell weight is incremented",
+                   UintegerValue (20),
+                   MakeUintegerAccessor (&LteFfrDistributedAlgorithm::m_rsrpDifferenceThreshold),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterPowerOffset",
+                   "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFfrDistributedAlgorithm::m_centerPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgePowerOffset",
+                   "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFfrDistributedAlgorithm::m_edgePowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeRbNum",
+                   "Number of RB that can be used in edge Sub-band",
+                   UintegerValue (8),
+                   MakeUintegerAccessor (&LteFfrDistributedAlgorithm::m_edgeRbNum),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in center area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFfrDistributedAlgorithm::m_centerAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in edge area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFfrDistributedAlgorithm::m_edgeAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+
+  ;
+  return tid;
+}
+
+
+void
+LteFfrDistributedAlgorithm::SetLteFfrSapUser (LteFfrSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrSapUser = s;
+}
+
+
+LteFfrSapProvider*
+LteFfrDistributedAlgorithm::GetLteFfrSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrSapProvider;
+}
+
+void
+LteFfrDistributedAlgorithm::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapUser = s;
+}
+
+
+LteFfrRrcSapProvider*
+LteFfrDistributedAlgorithm::GetLteFfrRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapProvider;
+}
+
+
+void
+LteFfrDistributedAlgorithm::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+  LteFfrAlgorithm::DoInitialize ();
+
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+
+  NS_LOG_LOGIC (this << " requesting Event A1 and A4 measurements"
+                     << " (threshold = 0" << ")");
+  LteRrcSap::ReportConfigEutra reportConfig;
+  reportConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
+  reportConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
+  reportConfig.threshold1.range = 0;
+  reportConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
+  reportConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS120;
+  m_rsrqMeasId = m_ffrRrcSapUser->AddUeMeasReportConfigForFfr (reportConfig);
+
+  LteRrcSap::ReportConfigEutra reportConfigA4;
+  reportConfigA4.eventId = LteRrcSap::ReportConfigEutra::EVENT_A4;
+  reportConfigA4.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRP;
+  reportConfigA4.threshold1.range = 0; // intentionally very low threshold
+  reportConfigA4.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRP;
+  reportConfigA4.reportInterval = LteRrcSap::ReportConfigEutra::MS120;
+  m_rsrpMeasId = m_ffrRrcSapUser->AddUeMeasReportConfigForFfr (reportConfigA4);
+
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  m_dlEdgeRbgMap.resize (m_dlBandwidth / rbgSize, false);
+  m_ulEdgeRbgMap.resize (m_ulBandwidth, false);
+  m_calculationEvent = Simulator::ScheduleNow (&LteFfrDistributedAlgorithm::Calculate, this);
+
+}
+
+void
+LteFfrDistributedAlgorithm::Reconfigure ()
+{
+  NS_LOG_FUNCTION (this);
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+  InitializeDownlinkRbgMaps ();
+  InitializeUplinkRbgMaps ();
+  m_needReconfiguration = false;
+}
+
+void
+LteFfrDistributedAlgorithm::SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteFfrDistributedAlgorithm::SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteFfrDistributedAlgorithm::InitializeDownlinkRbgMaps ()
+{
+  NS_LOG_FUNCTION (this);
+  m_dlRbgMap.clear ();
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  m_dlRbgMap.resize (m_dlBandwidth / rbgSize, false);
+}
+
+void
+LteFfrDistributedAlgorithm::InitializeUplinkRbgMaps ()
+{
+  NS_LOG_FUNCTION (this);
+  m_ulRbgMap.clear ();
+  m_ulRbgMap.resize (m_ulBandwidth, false);
+}
+
+std::vector <bool>
+LteFfrDistributedAlgorithm::DoGetAvailableDlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_needReconfiguration)
+    {
+      Reconfigure ();
+    }
+
+  if (m_dlRbgMap.empty ())
+    {
+      InitializeDownlinkRbgMaps ();
+    }
+
+  return m_dlRbgMap;
+}
+
+bool
+LteFfrDistributedAlgorithm::DoIsDlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  bool edgeRbg = m_dlEdgeRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+      return !edgeRbg;
+    }
+
+  bool edgeUe = false;
+  if (it->second == EdgeArea )
+    {
+      edgeUe = true;
+    }
+
+  return (edgeRbg && edgeUe) || (!edgeRbg && !edgeUe);
+}
+
+std::vector <bool>
+LteFfrDistributedAlgorithm::DoGetAvailableUlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_ulRbgMap.empty ())
+    {
+      InitializeUplinkRbgMaps ();
+    }
+
+  return m_ulRbgMap;
+}
+
+bool
+LteFfrDistributedAlgorithm::DoIsUlRbgAvailableForUe (int rbId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return true;
+    }
+
+  bool edgeRbg = m_ulEdgeRbgMap[rbId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+      return !edgeRbg;
+    }
+
+  bool edgeUe = false;
+  if (it->second == EdgeArea )
+    {
+      edgeUe = true;
+    }
+
+  return (edgeRbg && edgeUe) || (!edgeRbg && !edgeUe);
+}
+
+void
+LteFfrDistributedAlgorithm::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFfrDistributedAlgorithm::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFfrDistributedAlgorithm::DoReportUlCqiInfo (std::map <uint16_t, std::vector <double> > ulCqiMap)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+uint8_t
+LteFfrDistributedAlgorithm::DoGetTpc (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return 1;     // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
+    }
+
+  //TS36.213 Table 5.1.1.1-2
+  //   TPC   |   Accumulated Mode  |  Absolute Mode
+  //------------------------------------------------
+  //    0    |         -1          |      -4
+  //    1    |          0          |      -1
+  //    2    |          1          |       1
+  //    3    |          3          |       4
+  //------------------------------------------------
+  // here Absolute mode is used
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      return 1;
+    }
+
+  if (it->second == EdgeArea )
+    {
+      return m_edgeAreaTpc;
+    }
+  else
+    {
+      return m_centerAreaTpc;
+    }
+
+  return 1;
+}
+
+uint8_t
+LteFfrDistributedAlgorithm::DoGetMinContinuousUlBandwidth ()
+{
+  NS_LOG_FUNCTION (this);
+
+  uint8_t minContinuousUlBandwidth = m_ulBandwidth;
+
+  if (!m_enabledInUplink)
+    {
+      return minContinuousUlBandwidth;
+    }
+
+  minContinuousUlBandwidth =
+    ((m_edgeRbNum > 0 ) && (m_edgeRbNum < minContinuousUlBandwidth)) ? m_edgeRbNum : minContinuousUlBandwidth;
+
+  return minContinuousUlBandwidth;
+}
+
+void
+LteFfrDistributedAlgorithm::DoReportUeMeas (uint16_t rnti,
+                                            LteRrcSap::MeasResults measResults)
+{
+  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
+  NS_LOG_INFO ("CellId: " << m_cellId << " RNTI :" << rnti << " MeasId: " << (uint16_t) measResults.measId
+                          << " RSRP: " << (uint16_t)measResults.rsrpResult
+                          << " RSRQ: " << (uint16_t)measResults.rsrqResult);
+
+  if (measResults.measId == m_rsrqMeasId)
+    {
+      //check if it is center or edge UE
+      std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+      if (it == m_ues.end ())
+        {
+          m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+        }
+
+      it = m_ues.find (rnti);
+      if (measResults.rsrqResult >= m_egdeSubBandRsrqThreshold)
+        {
+          if (it->second != CenterArea)
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Center sub-band");
+              it->second = CenterArea;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_centerPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+      else
+        {
+          if (it->second != EdgeArea )
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Edge sub-band");
+              it->second = EdgeArea;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_edgePowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+    }
+  else if (measResults.measId == m_rsrpMeasId)
+    {
+      std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+      if (it == m_ues.end ())
+        {
+          m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+        }
+
+      UpdateNeighbourMeasurements (rnti, m_cellId, measResults.rsrpResult, measResults.rsrqResult);
+
+      if (measResults.haveMeasResultNeighCells
+          && !measResults.measResultListEutra.empty ())
+        {
+          for (std::list <LteRrcSap::MeasResultEutra>::iterator it = measResults.measResultListEutra.begin ();
+               it != measResults.measResultListEutra.end ();
+               ++it)
+            {
+              NS_ASSERT_MSG (it->haveRsrpResult == true,
+                             "RSRP measurement is missing from cellId " << it->physCellId);
+              NS_ASSERT_MSG (it->haveRsrqResult == true,
+                             "RSRQ measurement is missing from cellId " << it->physCellId);
+              UpdateNeighbourMeasurements (rnti, it->physCellId, it->rsrpResult, it->rsrqResult);
+
+              bool found = false;
+              for (std::vector<uint16_t>::iterator ncIt = m_neigborCell.begin (); ncIt != m_neigborCell.end (); ncIt++)
+                {
+                  if ((*ncIt) == it->physCellId)
+                    {
+                      found = true;
+                    }
+                }
+              if (found == false)
+                {
+                  m_neigborCell.push_back (it->physCellId);
+                }
+            }
+        }
+      else
+        {
+          NS_LOG_WARN (this << " Event A4 received without measurement results from neighbouring cells");
+        }
+    }
+  else
+    {
+      NS_LOG_WARN ("Ignoring measId " << (uint16_t) measResults.measId);
+    }
+}
+
+void
+LteFfrDistributedAlgorithm::Calculate ()
+{
+  NS_LOG_FUNCTION (this);
+  m_calculationEvent = Simulator::Schedule (m_calculationInterval, &LteFfrDistributedAlgorithm::Calculate, this);
+
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  uint16_t rbgNum = m_dlBandwidth / rbgSize;
+
+  m_cellWeightMap.clear ();
+  m_dlEdgeRbgMap.clear ();
+  m_dlEdgeRbgMap.resize (m_dlBandwidth / rbgSize, false);
+  m_ulEdgeRbgMap.clear ();
+  m_ulEdgeRbgMap.resize (m_ulBandwidth, false);
+
+  MeasurementTable_t::iterator it1;
+  MeasurementRow_t::iterator it2;
+  Ptr<UeMeasure> servingCellMeasures;
+  Ptr<UeMeasure> neighbourCellMeasures;
+
+  uint32_t edgeUeNum = 0;
+  std::map< uint16_t, uint8_t >::iterator areaIt;
+  for (areaIt = m_ues.begin (); areaIt != m_ues.end (); areaIt++)
+    {
+      if (areaIt->second == EdgeArea)
+        {
+          edgeUeNum++;
+        }
+    }
+
+  if (edgeUeNum != 0)
+    {
+      for (it1 = m_ueMeasures.begin (); it1 != m_ueMeasures.end (); it1++)
+        {
+          std::map< uint16_t, uint8_t >::iterator areaIt = m_ues.find (it1->first);
+          if (areaIt->second != EdgeArea)
+            {
+              continue;
+            }
+
+          servingCellMeasures = 0;
+          neighbourCellMeasures = 0;
+
+          it2 = it1->second.find (m_cellId);
+          if (it2 != it1->second.end ())
+            {
+              servingCellMeasures = it2->second;
+            }
+          else
+            {
+              continue;
+            }
+
+          for (it2 = it1->second.begin (); it2 != it1->second.end (); it2++)
+            {
+              if (it2->first != m_cellId)
+                {
+                  neighbourCellMeasures = it2->second;
+                }
+              else
+                {
+                  continue;
+                }
+
+              if (servingCellMeasures && neighbourCellMeasures)
+                {
+                  int16_t rsrpDifference = servingCellMeasures->m_rsrp - neighbourCellMeasures->m_rsrp;
+                  NS_LOG_INFO ("CellId: " << m_cellId << " UE RNTI: " << it1->first
+                                          << " NeighborCellId: " << neighbourCellMeasures->m_cellId
+                                          << " RSRP Serving: " << (int)servingCellMeasures->m_rsrp
+                                          << " RSRP Neighbor: " << (int)neighbourCellMeasures->m_rsrp
+                                          << " RSRP Difference: " << (int)rsrpDifference);
+
+                  if (rsrpDifference < m_rsrpDifferenceThreshold)
+                    {
+                      m_cellWeightMap[neighbourCellMeasures->m_cellId]++;
+                    }
+                }
+            }
+        }
+
+      std::map< uint16_t, uint64_t > metricA;
+      for (uint16_t i = 0; i < rbgNum; i++)
+        {
+          metricA[i] = 0;
+        }
+
+      std::map<uint16_t, uint32_t>::iterator cellIt;
+      for (cellIt = m_cellWeightMap.begin (); cellIt != m_cellWeightMap.end (); cellIt++)
+        {
+          NS_LOG_INFO ("CellId: " << m_cellId << " NeighborCellId: " << cellIt->first << " Weight: " << cellIt->second);
+
+          std::map<uint16_t, std::vector <bool> >::iterator rntpIt = m_rntp.find (cellIt->first);
+          if (rntpIt == m_rntp.end ())
+            {
+              continue;
+            }
+
+          for (uint8_t i = 0; i < rbgNum; i++)
+            {
+              metricA[i] += cellIt->second * rntpIt->second[i];
+            }
+        }
+
+      std::vector<uint16_t> sortedRbgByMetric;
+      std::multimap< uint64_t, uint16_t > sortedMetricA;
+      for (std::map<uint16_t, uint64_t>::const_iterator it = metricA.begin (); it != metricA.end (); ++it)
+        {
+          sortedMetricA.insert (std::pair<uint64_t, uint16_t> (it->second, it->first));
+        }
+
+      for (std::multimap< uint64_t, uint16_t >::const_iterator it = sortedMetricA.begin ();
+           it != sortedMetricA.end (); ++it)
+        {
+          sortedRbgByMetric.push_back (it->second);
+        }
+
+      for (int i = 0; i < m_edgeRbNum / rbgSize; i++)
+        {
+          m_dlEdgeRbgMap[ sortedRbgByMetric[i] ] = true;
+        }
+
+      for (int i = 0; i < m_edgeRbNum / rbgSize; i++)
+        {
+          uint32_t rbgIndex = sortedRbgByMetric[i];
+          for (int k = 0; k < rbgSize; k++)
+            {
+              uint32_t rbIndex = rbgSize * rbgIndex + k;
+              m_ulEdgeRbgMap[ rbIndex ] = true;
+            }
+        }
+    }
+
+  for (std::vector<uint16_t>::iterator ncIt = m_neigborCell.begin (); ncIt != m_neigborCell.end (); ncIt++)
+    {
+      SendLoadInformation ((*ncIt));
+    }
+}
+
+void
+LteFfrDistributedAlgorithm::SendLoadInformation (uint16_t targetCellId)
+{
+  NS_LOG_FUNCTION (this);
+
+  NS_LOG_INFO ("SendLoadInformation to CellId : " << targetCellId );
+
+  std::vector<EpcX2Sap::UlInterferenceOverloadIndicationItem> m_currentUlInterferenceOverloadIndicationList;
+  std::vector <EpcX2Sap::UlHighInterferenceInformationItem>  m_currentUlHighInterferenceInformationList;
+  EpcX2Sap::RelativeNarrowbandTxBand m_currentRelativeNarrowbandTxBand;
+
+  m_currentRelativeNarrowbandTxBand.rntpPerPrbList = m_dlEdgeRbgMap;
+
+  EpcX2Sap::CellInformationItem cii;
+  cii.sourceCellId = m_cellId;
+  cii.ulInterferenceOverloadIndicationList = m_currentUlInterferenceOverloadIndicationList;
+  cii.ulHighInterferenceInformationList = m_currentUlHighInterferenceInformationList;
+  cii.relativeNarrowbandTxBand = m_currentRelativeNarrowbandTxBand;
+
+  EpcX2Sap::LoadInformationParams params;
+  params.targetCellId = targetCellId;
+  params.cellInformationList.push_back (cii);
+
+  m_ffrRrcSapUser->SendLoadInformation (params);
+}
+
+void
+LteFfrDistributedAlgorithm::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_INFO ("CellId: " << m_cellId
+                          << " Recv X2 message: LOAD INFORMATION from CellId:" << params.cellInformationList[0].sourceCellId);
+
+  if (params.cellInformationList[0].sourceCellId > m_cellId)
+    {
+      return;
+    }
+
+  uint16_t neighborCellId = params.cellInformationList[0].sourceCellId;
+  std::map<uint16_t, std::vector <bool> >::iterator it = m_rntp.find (neighborCellId);
+  if (it != m_rntp.end ())
+    {
+      it->second = params.cellInformationList[0].relativeNarrowbandTxBand.rntpPerPrbList;
+    }
+  else
+    {
+      m_rntp.insert (std::pair<uint16_t, std::vector <bool> > (neighborCellId, params.cellInformationList[0].relativeNarrowbandTxBand.rntpPerPrbList));
+    }
+}
+
+void
+LteFfrDistributedAlgorithm::UpdateNeighbourMeasurements (uint16_t rnti,
+                                                         uint16_t cellId,
+                                                         uint8_t rsrp,
+                                                         uint8_t rsrq)
+{
+  NS_LOG_FUNCTION (this << rnti << cellId << (uint16_t) rsrq);
+
+  MeasurementTable_t::iterator it1;
+  it1 = m_ueMeasures.find (rnti);
+
+  if (it1 == m_ueMeasures.end ())
+    {
+      // insert a new UE entry
+      MeasurementRow_t row;
+      std::pair<MeasurementTable_t::iterator, bool> ret;
+      ret = m_ueMeasures.insert (std::pair<uint16_t, MeasurementRow_t> (rnti, row));
+      NS_ASSERT (ret.second);
+      it1 = ret.first;
+    }
+
+  NS_ASSERT (it1 != m_ueMeasures.end ());
+  Ptr<UeMeasure> cellMeasures;
+  std::map<uint16_t, Ptr<UeMeasure> >::iterator it2;
+  it2 = it1->second.find (cellId);
+
+  if (it2 != it1->second.end ())
+    {
+      cellMeasures = it2->second;
+      cellMeasures->m_cellId = cellId;
+      cellMeasures->m_rsrp = rsrp;
+      cellMeasures->m_rsrq = rsrq;
+    }
+  else
+    {
+      // insert a new cell entry
+      cellMeasures = Create<UeMeasure> ();
+      cellMeasures->m_cellId = cellId;
+      cellMeasures->m_rsrp = rsrp;
+      cellMeasures->m_rsrq = rsrq;
+      it1->second[cellId] = cellMeasures;
+    }
+
+} // end of UpdateNeighbourMeasurements
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-distributed-algorithm.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,158 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FFR_DISTRIBUTED_ALGORITHM_H
+#define LTE_FFR_DISTRIBUTED_ALGORITHM_H
+
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-ffr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
+#include <ns3/lte-rrc-sap.h>
+
+namespace ns3 {
+
+/**
+ * \brief Distributed Fractional Frequency Reuse algorithm implementation.
+ */
+class LteFfrDistributedAlgorithm : public LteFfrAlgorithm
+{
+public:
+  LteFfrDistributedAlgorithm ();
+  virtual ~LteFfrDistributedAlgorithm ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  // inherited from LteFfrAlgorithm
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s);
+  virtual LteFfrSapProvider* GetLteFfrSapProvider ();
+
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s);
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider ();
+
+  // let the forwarder class access the protected and private members
+  friend class MemberLteFfrSapProvider<LteFfrDistributedAlgorithm>;
+  friend class MemberLteFfrRrcSapProvider<LteFfrDistributedAlgorithm>;
+
+protected:
+  // inherited from Object
+  virtual void DoInitialize ();
+  virtual void DoDispose ();
+
+  virtual void Reconfigure ();
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+  virtual std::vector <bool> DoGetAvailableDlRbg ();
+  virtual bool DoIsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> DoGetAvailableUlRbg ();
+  virtual bool DoIsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t DoGetTpc (uint16_t rnti);
+  virtual uint8_t DoGetMinContinuousUlBandwidth ();
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+  void SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void InitializeDownlinkRbgMaps ();
+  void InitializeUplinkRbgMaps ();
+
+  void UpdateNeighbourMeasurements (uint16_t rnti, uint16_t cellId, uint8_t rsrp, uint8_t rsrq);
+
+  void Calculate ();
+  void SendLoadInformation (uint16_t targetCellId);
+
+  // FFR SAP
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
+
+  // FFR RRF SAP
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
+  std::vector <bool> m_dlRbgMap;
+  std::vector <bool> m_ulRbgMap;
+
+  uint8_t m_edgeRbNum;
+  std::vector <bool> m_dlEdgeRbgMap;
+  std::vector <bool> m_ulEdgeRbgMap;
+
+  enum UePosition
+  {
+    AreaUnset,
+    CenterArea,
+    EdgeArea
+  };
+
+  std::map< uint16_t, uint8_t > m_ues;
+
+  uint8_t m_egdeSubBandRsrqThreshold;
+
+  uint8_t m_centerPowerOffset;
+  uint8_t m_edgePowerOffset;
+
+  uint8_t m_centerAreaTpc;
+  uint8_t m_edgeAreaTpc;
+
+  Time m_calculationInterval;
+  EventId m_calculationEvent;
+
+  // The expected measurement identity
+  uint8_t m_rsrqMeasId;
+  uint8_t m_rsrpMeasId;
+
+  /**
+   * \brief Measurements reported by a UE for a cell ID.
+   *
+   * The values are quantized according 3GPP TS 36.133 section 9.1.4 and 9.1.7.
+   */
+  class UeMeasure : public SimpleRefCount<UeMeasure>
+  {
+public:
+    uint16_t m_cellId;
+    uint8_t m_rsrp;
+    uint8_t m_rsrq;
+  };
+
+  //               cellId
+  typedef std::map<uint16_t, Ptr<UeMeasure> > MeasurementRow_t;
+  //               rnti
+  typedef std::map<uint16_t, MeasurementRow_t> MeasurementTable_t;
+  MeasurementTable_t m_ueMeasures;
+
+  std::vector<uint16_t> m_neigborCell;
+
+  uint8_t m_rsrpDifferenceThreshold;
+
+  std::map<uint16_t, uint32_t> m_cellWeightMap;
+
+  std::map<uint16_t, std::vector <bool> > m_rntp;
+
+}; // end of class LteFfrDistributedAlgorithm
+
+} // end of namespace ns3
+
+#endif /* LTE_FR_DISTRIBUTED_ALGORITHM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-enhanced-algorithm.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,907 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-ffr-enhanced-algorithm.h"
+#include "ns3/ff-mac-common.h"
+#include "ns3/lte-common.h"
+#include "ns3/lte-vendor-specific-parameters.h"
+#include <ns3/log.h>
+#include "ns3/boolean.h"
+#include <ns3/double.h>
+#include <cfloat>
+
+NS_LOG_COMPONENT_DEFINE ("LteFfrEnhancedAlgorithm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteFfrEnhancedAlgorithm);
+
+static const double SpectralEfficiencyForCqi[16] = {
+  0.0, // out of range
+  0.15, 0.23, 0.38, 0.6, 0.88, 1.18,
+  1.48, 1.91, 2.41,
+  2.73, 3.32, 3.9, 4.52, 5.12, 5.55
+};
+
+static const struct FfrEnhancedDownlinkDefaultConfiguration
+{
+  uint8_t cellId;
+  uint8_t dlBandwidth;
+  uint8_t dlSubBandOffset;
+  uint8_t dlReuse3SubBandwidth;
+  uint8_t dlReuse1SubBandwidth;
+} g_ffrEnhancedDownlinkDefaultConfiguration[] = {
+  { 1, 25, 0, 4, 4},
+  { 2, 25, 8, 4, 4},
+  { 3, 25, 16, 4, 4},
+  { 1, 50, 0, 9, 6},
+  { 2, 50, 15, 9, 6},
+  { 3, 50, 30, 9, 6},
+  { 1, 75, 0, 8, 16},
+  { 2, 75, 24, 8, 16},
+  { 3, 75, 48, 8, 16},
+  { 1, 100, 0, 16, 16},
+  { 2, 100, 32, 16, 16},
+  { 3, 100, 64, 16, 16}
+};
+
+static const struct FfrEnhancedUplinkDefaultConfiguration
+{
+  uint8_t cellId;
+  uint8_t ulBandwidth;
+  uint8_t ulSubBandOffset;
+  uint8_t ulReuse3SubBandwidth;
+  uint8_t ulReuse1SubBandwidth;
+} g_ffrEnhancedUplinkDefaultConfiguration[] = {
+  { 1, 25, 0, 4, 4},
+  { 2, 25, 8, 4, 4},
+  { 3, 25, 16, 4, 4},
+  { 1, 50, 0, 9, 6},
+  { 2, 50, 15, 9, 6},
+  { 3, 50, 30, 9, 6},
+  { 1, 75, 0, 8, 16},
+  { 2, 75, 24, 8, 16},
+  { 3, 75, 48, 8, 16},
+  { 1, 100, 0, 16, 16},
+  { 2, 100, 32, 16, 16},
+  { 3, 100, 64, 16, 16}
+};
+
+const uint16_t NUM_DOWNLINK_CONFS (sizeof (g_ffrEnhancedDownlinkDefaultConfiguration) / sizeof (FfrEnhancedDownlinkDefaultConfiguration));
+const uint16_t NUM_UPLINK_CONFS (sizeof (g_ffrEnhancedUplinkDefaultConfiguration) / sizeof (FfrEnhancedUplinkDefaultConfiguration));
+
+
+LteFfrEnhancedAlgorithm::LteFfrEnhancedAlgorithm ()
+  : m_ffrSapUser (0),
+    m_ffrRrcSapUser (0),
+    m_measId (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_ffrSapProvider = new MemberLteFfrSapProvider<LteFfrEnhancedAlgorithm> (this);
+  m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFfrEnhancedAlgorithm> (this);
+}
+
+
+LteFfrEnhancedAlgorithm::~LteFfrEnhancedAlgorithm ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteFfrEnhancedAlgorithm::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ffrSapProvider;
+  delete m_ffrRrcSapProvider;
+}
+
+
+TypeId
+LteFfrEnhancedAlgorithm::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFfrEnhancedAlgorithm")
+    .SetParent<LteFfrAlgorithm> ()
+    .AddConstructor<LteFfrEnhancedAlgorithm> ()
+    .AddAttribute ("UlSubBandOffset",
+                   "Uplink SubBand Offset for this cell in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_ulSubBandOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlReuse3SubBandwidth",
+                   "Uplink Reuse 3 SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (4),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_ulReuse3SubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlReuse1SubBandwidth",
+                   "Uplink Reuse 1 SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (4),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_ulReuse1SubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlSubBandOffset",
+                   "Downlink SubBand Offset for this cell in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_dlSubBandOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlReuse3SubBandwidth",
+                   "Downlink Reuse 3 SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (4),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_dlReuse3SubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlReuse1SubBandwidth",
+                   "Downlink Reuse 1 SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (4),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_dlReuse1SubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("RsrqThreshold",
+                   "If the RSRQ of is worse than this threshold, UE should be served in Edge sub-band",
+                   UintegerValue (26),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_rsrqThreshold),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterAreaPowerOffset",
+                   "PdschConfigDedicated::Pa value for Center Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_centerAreaPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeAreaPowerOffset",
+                   "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_edgeAreaPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlCqiThreshold",
+                   "If the DL-CQI for RBG of is higher than this threshold, transmission on RBG is possible",
+                   UintegerValue (15),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_dlCqiThreshold),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlCqiThreshold",
+                   "If the UL-CQI for RBG of is higher than this threshold, transmission on RBG is possible",
+                   UintegerValue (15),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_ulCqiThreshold),
+                   MakeUintegerChecker <uint8_t> ())
+    .AddAttribute ("CenterAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in center area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_centerAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in edge area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFfrEnhancedAlgorithm::m_edgeAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+  ;
+  return tid;
+}
+
+
+void
+LteFfrEnhancedAlgorithm::SetLteFfrSapUser (LteFfrSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrSapUser = s;
+}
+
+
+LteFfrSapProvider*
+LteFfrEnhancedAlgorithm::GetLteFfrSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrSapProvider;
+}
+
+void
+LteFfrEnhancedAlgorithm::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapUser = s;
+}
+
+
+LteFfrRrcSapProvider*
+LteFfrEnhancedAlgorithm::GetLteFfrRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapProvider;
+}
+
+
+void
+LteFfrEnhancedAlgorithm::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+  LteFfrAlgorithm::DoInitialize ();
+
+  NS_ASSERT_MSG (m_dlBandwidth > 24,"DlBandwidth must be at least 25 to use EFFR algorithm");
+  NS_ASSERT_MSG (m_ulBandwidth > 24,"UlBandwidth must be at least 25 to use EFFR algorithm");
+
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+
+  NS_LOG_LOGIC (this << " requesting Event A1 measurements"
+                     << " (threshold = 0" << ")");
+  LteRrcSap::ReportConfigEutra reportConfig;
+  reportConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
+  reportConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
+  reportConfig.threshold1.range = 0;
+  reportConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
+  reportConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS120;
+  m_measId = m_ffrRrcSapUser->AddUeMeasReportConfigForFfr (reportConfig);
+}
+
+void
+LteFfrEnhancedAlgorithm::Reconfigure ()
+{
+  NS_LOG_FUNCTION (this);
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+  InitializeDownlinkRbgMaps ();
+  InitializeUplinkRbgMaps ();
+  m_needReconfiguration = false;
+}
+
+void
+LteFfrEnhancedAlgorithm::SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_DOWNLINK_CONFS; ++i)
+    {
+      if ((g_ffrEnhancedDownlinkDefaultConfiguration[i].cellId == cellId)
+          && g_ffrEnhancedDownlinkDefaultConfiguration[i].dlBandwidth == m_dlBandwidth)
+        {
+          m_dlSubBandOffset = g_ffrEnhancedDownlinkDefaultConfiguration[i].dlSubBandOffset;
+          m_dlReuse3SubBandwidth = g_ffrEnhancedDownlinkDefaultConfiguration[i].dlReuse3SubBandwidth;
+          m_dlReuse1SubBandwidth = g_ffrEnhancedDownlinkDefaultConfiguration[i].dlReuse1SubBandwidth;
+        }
+    }
+}
+
+void
+LteFfrEnhancedAlgorithm::SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_UPLINK_CONFS; ++i)
+    {
+      if ((g_ffrEnhancedUplinkDefaultConfiguration[i].cellId == cellId)
+          && g_ffrEnhancedUplinkDefaultConfiguration[i].ulBandwidth == m_ulBandwidth)
+        {
+          m_ulSubBandOffset = g_ffrEnhancedUplinkDefaultConfiguration[i].ulSubBandOffset;
+          m_ulReuse3SubBandwidth = g_ffrEnhancedUplinkDefaultConfiguration[i].ulReuse3SubBandwidth;
+          m_ulReuse1SubBandwidth = g_ffrEnhancedUplinkDefaultConfiguration[i].ulReuse1SubBandwidth;
+        }
+    }
+}
+
+int
+LteFfrEnhancedAlgorithm::GetCqiFromSpectralEfficiency (double s)
+{
+  NS_LOG_FUNCTION (s);
+  NS_ASSERT_MSG (s >= 0.0, "negative spectral efficiency = " << s);
+  int cqi = 0;
+  while ((cqi < 15) && (SpectralEfficiencyForCqi[cqi + 1] < s))
+    {
+      ++cqi;
+    }
+  NS_LOG_LOGIC ("cqi = " << cqi);
+  return cqi;
+}
+
+void
+LteFfrEnhancedAlgorithm::InitializeDownlinkRbgMaps ()
+{
+  m_dlRbgMap.clear ();
+  m_dlReuse3RbgMap.clear ();
+  m_dlReuse1RbgMap.clear ();
+  m_dlPrimarySegmentRbgMap.clear ();
+  m_dlSecondarySegmentRbgMap.clear ();
+
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  m_dlRbgMap.resize (m_dlBandwidth / rbgSize, true);
+
+  m_dlReuse3RbgMap.resize (m_dlBandwidth / rbgSize, false);
+  m_dlReuse1RbgMap.resize (m_dlBandwidth / rbgSize, false);
+  m_dlPrimarySegmentRbgMap.resize (m_dlBandwidth / rbgSize, false);
+  m_dlSecondarySegmentRbgMap.resize (m_dlBandwidth / rbgSize, true);
+
+  NS_ASSERT_MSG (m_dlSubBandOffset <= m_dlBandwidth,"DlSubBandOffset higher than DlBandwidth");
+  NS_ASSERT_MSG (m_dlSubBandOffset + m_dlReuse3SubBandwidth + m_dlReuse1SubBandwidth <= m_dlBandwidth,
+                 "DlSubBandOffset + DlReuse3SubBandwidth + DlReuse1SubBandwidth  higher than DlBandwidth");
+
+  for (uint8_t i = 0; i < m_dlReuse3SubBandwidth / rbgSize; i++)
+    {
+      int offset = m_dlSubBandOffset / rbgSize;
+      uint8_t index = offset + i;
+      m_dlReuse3RbgMap[index] = true;
+      m_dlPrimarySegmentRbgMap[index] = true;
+      m_dlRbgMap[index] = false;
+    }
+
+  for (uint8_t i = 0; i < m_dlReuse1SubBandwidth / rbgSize; i++)
+    {
+      int offset = (m_dlSubBandOffset + m_dlReuse3SubBandwidth) / rbgSize;
+      uint8_t index = offset + i;
+      m_dlReuse1RbgMap[index] = true;
+      m_dlPrimarySegmentRbgMap[index] = true;
+      m_dlSecondarySegmentRbgMap[index] = false;
+      m_dlRbgMap[index] = false;
+    }
+
+  for (uint8_t i = 0; i < m_dlReuse3SubBandwidth / rbgSize; i++)
+    {
+      uint8_t offset = (m_dlReuse3SubBandwidth + m_dlReuse1SubBandwidth) / rbgSize;
+
+      uint8_t index = 0 * offset + i;
+      m_dlSecondarySegmentRbgMap[index] = false;
+
+      index = 1 * offset + i;
+      m_dlSecondarySegmentRbgMap[index] = false;
+
+      index = 2 * offset + i;
+      m_dlSecondarySegmentRbgMap[index] = false;
+    }
+}
+
+
+void
+LteFfrEnhancedAlgorithm::InitializeUplinkRbgMaps ()
+{
+  m_ulRbgMap.clear ();
+  m_ulReuse3RbgMap.clear ();
+  m_ulReuse1RbgMap.clear ();
+  m_ulPrimarySegmentRbgMap.clear ();
+  m_ulSecondarySegmentRbgMap.clear ();
+
+  if (!m_enabledInUplink)
+    {
+      m_ulRbgMap.resize (m_ulBandwidth, false);
+      return;
+    }
+
+  m_ulRbgMap.resize (m_ulBandwidth, true);
+  m_ulReuse3RbgMap.resize (m_ulBandwidth, false);
+  m_ulReuse1RbgMap.resize (m_ulBandwidth, false);
+  m_ulPrimarySegmentRbgMap.resize (m_ulBandwidth, false);
+  m_ulSecondarySegmentRbgMap.resize (m_ulBandwidth, true);
+
+
+  NS_ASSERT_MSG (m_ulSubBandOffset <= m_ulBandwidth, "UlSubBandOffset higher than UlBandwidth");
+  NS_ASSERT_MSG (m_ulSubBandOffset + m_ulReuse3SubBandwidth + m_ulReuse1SubBandwidth <= m_ulBandwidth,
+                 "UlSubBandOffset + UlReuse3SubBandwidth + UlReuse1SubBandwidth higher than UlBandwidth");
+
+
+  for (uint8_t i = 0; i < m_ulReuse3SubBandwidth; i++)
+    {
+      int offset = m_ulSubBandOffset;
+      uint8_t index = offset + i;
+      m_ulReuse3RbgMap[index] = true;
+      m_ulPrimarySegmentRbgMap[index] = true;
+      m_ulRbgMap[index] = false;
+    }
+
+  for (uint8_t i = 0; i < m_ulReuse1SubBandwidth; i++)
+    {
+      int offset = (m_ulSubBandOffset + m_ulReuse3SubBandwidth);
+      uint8_t index = offset + i;
+      m_ulReuse1RbgMap[index] = true;
+      m_ulPrimarySegmentRbgMap[index] = true;
+      m_ulSecondarySegmentRbgMap[index] = false;
+      m_ulRbgMap[index] = false;
+    }
+
+  for (uint8_t i = 0; i < m_ulReuse3SubBandwidth; i++)
+    {
+      uint8_t offset = m_ulReuse3SubBandwidth + m_ulReuse1SubBandwidth;
+
+      uint8_t index = 0 * offset + i;
+      m_ulSecondarySegmentRbgMap[index] = false;
+
+      index = 1 * offset + i;
+      m_ulSecondarySegmentRbgMap[index] = false;
+
+      index = 2 * offset + i;
+      m_ulSecondarySegmentRbgMap[index] = false;
+
+    }
+}
+
+std::vector <bool>
+LteFfrEnhancedAlgorithm::DoGetAvailableDlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_needReconfiguration)
+    {
+      Reconfigure ();
+    }
+
+  if (m_dlRbgMap.empty ())
+    {
+      InitializeDownlinkRbgMaps ();
+    }
+
+  std::vector <bool> rbgMap = m_dlRbgMap;
+
+  std::map <uint16_t, std::vector<bool> >::iterator it;
+  for (it = m_dlRbgAvailableforUe.begin (); it != m_dlRbgAvailableforUe.end (); it++)
+    {
+      NS_LOG_INFO ("RNTI : " << it->first);
+      std::vector<bool> rbgAvailableMap = it->second;
+      for (uint32_t i = 0; i < rbgMap.size (); i++)
+        {
+          NS_LOG_INFO ("\t rbgId: " << i << " available " << (int)rbgAvailableMap.at (i));
+          if ( rbgAvailableMap.at (i) == true)
+            {
+              rbgMap.at (i) = false;
+            }
+        }
+    }
+
+  return rbgMap;
+}
+
+bool
+LteFfrEnhancedAlgorithm::DoIsDlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  bool isReuse3Rbg = m_dlReuse3RbgMap[rbgId];
+  bool isReuse1Rbg = m_dlReuse1RbgMap[rbgId];
+  bool isPrimarySegmentRbg     = m_dlPrimarySegmentRbgMap[rbgId];
+  bool isSecondarySegmentRbg   = m_dlSecondarySegmentRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+    }
+
+  it = m_ues.find (rnti);
+
+  //if UE area is unknown, serve UE in edge area RBGs
+  if (it->second == AreaUnset)
+    {
+      return isReuse3Rbg;
+    }
+
+
+  bool isCenterUe = false;
+  bool isEdgeUe   = false;
+
+  if (it->second == CenterArea )
+    {
+      isCenterUe = true;
+    }
+  else if (it->second == EdgeArea)
+    {
+      isEdgeUe = true;
+    }
+
+  if (isPrimarySegmentRbg)
+    {
+      NS_LOG_INFO ("PRIMARY SEGMENT RNTI: " << rnti  << "  rbgId: " << rbgId );
+      return (isReuse1Rbg && isCenterUe) || (isReuse3Rbg && isEdgeUe);
+    }
+  else if (isSecondarySegmentRbg && isCenterUe)
+    {
+      //check if RB can be used by UE based on CQI information
+      NS_LOG_INFO ("SECONDARY SEGMENT RNTI: " << rnti  << "  rbgId: " << rbgId );
+      std::map <uint16_t, std::vector<bool> >::iterator it = m_dlRbgAvailableforUe.find (rnti);
+      if (it != m_dlRbgAvailableforUe.end ())
+        {
+          NS_LOG_INFO ("RNTI: " << rnti  << "  rbgId: " << rbgId << "  available: " << it->second.at (rbgId));
+          if (it->second.at (rbgId) == true)
+            {
+              return true;
+            }
+        }
+      return false;
+    }
+
+  return false;
+}
+
+std::vector <bool>
+LteFfrEnhancedAlgorithm::DoGetAvailableUlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_ulRbgMap.empty ())
+    {
+      InitializeUplinkRbgMaps ();
+    }
+
+  if (!m_enabledInUplink)
+    {
+      return m_ulRbgMap;
+    }
+
+  std::vector <bool> rbgMap = m_ulRbgMap;
+
+  std::map <uint16_t, std::vector<bool> >::iterator it;
+  for (it = m_ulRbAvailableforUe.begin (); it != m_ulRbAvailableforUe.end (); it++)
+    {
+      NS_LOG_INFO ("RNTI : " << it->first);
+      std::vector<bool> rbAvailableMap = it->second;
+      for (uint32_t i = 0; i < rbgMap.size (); i++)
+        {
+          NS_LOG_INFO ("\t rbgId: " << i << " available " << (int)rbAvailableMap.at (i));
+          if ( rbAvailableMap.at (i) == true)
+            {
+              rbgMap.at (i) = false;
+            }
+        }
+    }
+
+  return rbgMap;
+}
+
+bool
+LteFfrEnhancedAlgorithm::DoIsUlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return true;
+    }
+
+  bool isReuse3Rbg = m_ulReuse3RbgMap[rbgId];
+  bool isReuse1Rbg = m_ulReuse1RbgMap[rbgId];
+  bool isPrimarySegmentRbg     = m_ulPrimarySegmentRbgMap[rbgId];
+  bool isSecondarySegmentRbg   = m_ulSecondarySegmentRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+    }
+
+  it = m_ues.find (rnti);
+
+  //if UE area is unknown, serve UE in edge area RBGs
+  if (it->second == AreaUnset)
+    {
+      return isReuse3Rbg;
+    }
+
+  bool isCenterUe = false;
+  bool isEdgeUe   = false;
+
+  if (it->second == CenterArea )
+    {
+      isCenterUe = true;
+    }
+  else if (it->second == EdgeArea)
+    {
+      isEdgeUe = true;
+    }
+
+  if (isPrimarySegmentRbg)
+    {
+      return (isReuse1Rbg && isCenterUe) || (isReuse3Rbg && isEdgeUe);
+    }
+  else if (isSecondarySegmentRbg && isCenterUe)
+    {
+      //check if RB can be used by UE based on CQI information
+      NS_LOG_INFO ("UL SECONDARY SEGMENT RNTI: " << rnti  << "  rbgId: " << rbgId );
+      std::map <uint16_t, std::vector<bool> >::iterator it = m_ulRbAvailableforUe.find (rnti);
+      if (it != m_ulRbAvailableforUe.end ())
+        {
+          NS_LOG_INFO ("RNTI: " << rnti  << "  rbgId: " << rbgId << "  available: " << it->second.at (rbgId));
+          if (it->second.at (rbgId) == true)
+            {
+              return true;
+            }
+        }
+      return false;
+    }
+
+  return false;
+}
+
+void
+LteFfrEnhancedAlgorithm::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_dlCqi.clear ();
+  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
+    {
+      if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
+        {
+          NS_LOG_INFO ("subband CQI reporting high layer configured");
+          // subband CQI reporting high layer configured
+          std::map <uint16_t,SbMeasResult_s>::iterator it;
+          uint16_t rnti = params.m_cqiList.at (i).m_rnti;
+
+          std::map< uint16_t, uint8_t >::iterator ueIt = m_ues.find (rnti);
+          if (ueIt != m_ues.end ())
+            {
+              if (ueIt->second != CenterArea )
+                {
+                  continue;
+                }
+            }
+          else
+            {
+              continue;
+            }
+
+          it = m_dlCqi.find (rnti);
+          if (it == m_dlCqi.end ())
+            {
+              // create the new entry
+              m_dlCqi.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
+            }
+          else
+            {
+              // update the CQI value and refresh correspondent timer
+              (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
+            }
+        }
+      else
+        {
+          NS_LOG_ERROR (this << " CQI type unknown");
+        }
+    }
+
+  uint32_t rbgSize = GetRbgSize (m_dlBandwidth);
+  m_dlRbgAvailableforUe.clear ();
+  std::map <uint16_t,SbMeasResult_s>::iterator it;
+  for (it = m_dlCqi.begin (); it != m_dlCqi.end (); it++)
+    {
+      uint16_t rnti = it->first;
+      std::vector<bool> rbgAvailableMap;
+
+      for (uint32_t i = 0; i < (*it).second.m_higherLayerSelected.size (); i++)
+        {
+          uint8_t rbgCqi = (*it).second.m_higherLayerSelected.at (i).m_sbCqi.at (0);
+
+          if (i > m_dlBandwidth / rbgSize)
+            {
+              continue;
+            }
+          NS_LOG_INFO (this << " RNTI " << rnti << " RBG  " << i << " DL-CQI: " << (int)rbgCqi);
+
+          bool rbgAvailable = (rbgCqi > m_dlCqiThreshold) ? true : false;
+
+          bool isSecondarySegmentRbg = false;
+          if (i < m_dlSecondarySegmentRbgMap.size ())
+            {
+              isSecondarySegmentRbg = m_dlSecondarySegmentRbgMap[i];
+            }
+
+          rbgAvailable = (isSecondarySegmentRbg == true) ? rbgAvailable : false;
+
+          rbgAvailableMap.push_back (rbgAvailable);
+        }
+
+      m_dlRbgAvailableforUe.insert ( std::pair<uint16_t, std::vector<bool> > (rnti, rbgAvailableMap ) );
+    }
+
+  m_ulRbAvailableforUe.clear ();
+  for (std::map<uint16_t, std::vector<bool> >::iterator it = m_dlRbgAvailableforUe.begin ();
+       it != m_dlRbgAvailableforUe.end (); it++)
+    {
+      uint16_t rnti = it->first;
+      std::vector<bool> dlRbgAvailableMap = it->second;
+      std::vector<bool> ulRbAvailableMap;
+      ulRbAvailableMap.resize (m_ulBandwidth, false);
+
+      for (uint32_t j = 0; j < dlRbgAvailableMap.size (); j++)
+        {
+          uint32_t index = rbgSize * j;
+          for (uint32_t i = 0; i < rbgSize; i++)
+            {
+              index = index + i;
+              ulRbAvailableMap[index] = dlRbgAvailableMap[j];
+            }
+        }
+
+      m_ulRbAvailableforUe.insert ( std::pair<uint16_t, std::vector<bool> > (rnti, ulRbAvailableMap ) );
+    }
+
+  return;
+}
+
+void
+LteFfrEnhancedAlgorithm::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  if (params.m_ulCqi.m_type == UlCqi_s::SRS)
+    {
+      // get the RNTI from vendor specific parameters
+      uint16_t rnti = 0;
+      for (uint32_t j = 0; j < m_ulBandwidth; j++)
+        {
+          double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
+          double s = log2 ( 1 + (
+                              std::pow (10, sinr / 10 )  /
+                              ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
+          int cqi = GetCqiFromSpectralEfficiency (s);
+          NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB  " << j << " value " << sinr << " UL-CQI: " << cqi);
+        }
+    }
+}
+
+void
+LteFfrEnhancedAlgorithm::DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap )
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+double
+LteFfrEnhancedAlgorithm::EstimateUlSinr (uint16_t rnti, uint16_t rb, std::map <uint16_t, std::vector <double> > ulCqiMap)
+{
+  std::map <uint16_t, std::vector <double> >::iterator itCqi = ulCqiMap.find (rnti);
+  if (itCqi == ulCqiMap.end ())
+    {
+      // no cqi info about this UE
+      return (NO_SINR);
+    }
+  else
+    {
+      // take the average SINR value among the available
+      double sinrSum = 0;
+      int sinrNum = 0;
+      for (uint32_t i = 0; i < m_ulBandwidth; i++)
+        {
+          double sinr = (*itCqi).second.at (i);
+          if (sinr != NO_SINR)
+            {
+              sinrSum += sinr;
+              sinrNum++;
+            }
+        }
+      double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
+      // store the value
+      (*itCqi).second.at (rb) = estimatedSinr;
+      return (estimatedSinr);
+    }
+}
+
+uint8_t
+LteFfrEnhancedAlgorithm::DoGetTpc (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return 1;     // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
+    }
+
+  //TS36.213 Table 5.1.1.1-2
+  //   TPC   |   Accumulated Mode  |  Absolute Mode
+  //------------------------------------------------
+  //    0    |         -1          |      -4
+  //    1    |          0          |      -1
+  //    2    |          1          |       1
+  //    3    |          3          |       4
+  //------------------------------------------------
+  // here Absolute mode is used
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      return 1;
+    }
+
+  if (it->second == EdgeArea )
+    {
+      return m_edgeAreaTpc;
+    }
+  else
+    {
+      return m_centerAreaTpc;
+    }
+
+  return 1;
+}
+
+uint8_t
+LteFfrEnhancedAlgorithm::DoGetMinContinuousUlBandwidth ()
+{
+  NS_LOG_FUNCTION (this);
+
+  uint8_t minContinuousUlBandwidth = m_ulBandwidth;
+
+  if (!m_enabledInUplink)
+    {
+      return minContinuousUlBandwidth;
+    }
+
+  minContinuousUlBandwidth =
+    ((m_ulReuse3SubBandwidth > 0 ) && (m_ulReuse3SubBandwidth < minContinuousUlBandwidth)) ? m_ulReuse3SubBandwidth : minContinuousUlBandwidth;
+
+  minContinuousUlBandwidth =
+    ((m_ulReuse1SubBandwidth > 0 ) && (m_ulReuse1SubBandwidth < minContinuousUlBandwidth)) ? m_ulReuse1SubBandwidth : minContinuousUlBandwidth;
+
+  NS_LOG_INFO ("minContinuousUlBandwidth: " << (int)minContinuousUlBandwidth);
+
+  return minContinuousUlBandwidth;
+}
+
+
+void
+LteFfrEnhancedAlgorithm::DoReportUeMeas (uint16_t rnti,
+                                         LteRrcSap::MeasResults measResults)
+{
+  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
+  NS_LOG_INFO ("RNTI :" << rnti << " MeasId: " << (uint16_t) measResults.measId
+                        << " RSRP: " << (uint16_t)measResults.rsrpResult
+                        << " RSRQ: " << (uint16_t)measResults.rsrqResult);
+
+  if (measResults.measId != m_measId)
+    {
+      NS_LOG_WARN ("Ignoring measId " << (uint16_t) measResults.measId);
+    }
+  else
+    {
+      std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+      if (it == m_ues.end ())
+        {
+          m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+        }
+
+      it = m_ues.find (rnti);
+      if (measResults.rsrqResult < m_rsrqThreshold)
+        {
+          if (it->second != EdgeArea)
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Edge sub-band");
+              it->second = EdgeArea;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_edgeAreaPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+      else
+        {
+          if (it->second != CenterArea)
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Center sub-band");
+              it->second = CenterArea;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_centerAreaPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+    }
+}
+void
+LteFfrEnhancedAlgorithm::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-enhanced-algorithm.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,159 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FFR_ENHANCED_ALGORITHM_H
+#define LTE_FFR_ENHANCED_ALGORITHM_H
+
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-ffr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
+#include <ns3/lte-rrc-sap.h>
+#include <map>
+
+// value for SINR outside the range defined by FF-API, used to indicate that there
+// is no CQI for this element
+#define NO_SINR -5000
+
+namespace ns3 {
+
+/**
+ * \brief Enhanced Fractional Frequency Reuse algorithm implementation
+ */
+class LteFfrEnhancedAlgorithm : public LteFfrAlgorithm
+{
+public:
+  /**
+   * \brief Creates a trivial ffr algorithm instance.
+   */
+  LteFfrEnhancedAlgorithm ();
+  virtual ~LteFfrEnhancedAlgorithm ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  // inherited from LteFfrAlgorithm
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s);
+  virtual LteFfrSapProvider* GetLteFfrSapProvider ();
+
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s);
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider ();
+
+  // let the forwarder class access the protected and private members
+  friend class MemberLteFfrSapProvider<LteFfrEnhancedAlgorithm>;
+  friend class MemberLteFfrRrcSapProvider<LteFfrEnhancedAlgorithm>;
+
+protected:
+  // inherited from Object
+  virtual void DoInitialize ();
+  virtual void DoDispose ();
+
+  virtual void Reconfigure ();
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+  virtual std::vector <bool> DoGetAvailableDlRbg ();
+  virtual bool DoIsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> DoGetAvailableUlRbg ();
+  virtual bool DoIsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t DoGetTpc (uint16_t rnti);
+  virtual uint8_t DoGetMinContinuousUlBandwidth ();
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+  void SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void InitializeDownlinkRbgMaps ();
+  void InitializeUplinkRbgMaps ();
+
+  double EstimateUlSinr (uint16_t rnti, uint16_t rb, std::map <uint16_t, std::vector <double> > ulCqiMap);
+  int GetCqiFromSpectralEfficiency (double s);
+
+  // FFR SAP
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
+
+  // FFR RRF SAP
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
+  uint8_t m_dlSubBandOffset;
+  uint8_t m_dlReuse3SubBandwidth;
+  uint8_t m_dlReuse1SubBandwidth;
+
+  uint8_t m_ulSubBandOffset;
+  uint8_t m_ulReuse3SubBandwidth;
+  uint8_t m_ulReuse1SubBandwidth;
+
+  std::vector <bool> m_dlRbgMap;
+  std::vector <bool> m_ulRbgMap;
+
+  std::vector <bool> m_dlReuse3RbgMap;
+  std::vector <bool> m_dlReuse1RbgMap;
+  std::vector <bool> m_dlPrimarySegmentRbgMap;
+  std::vector <bool> m_dlSecondarySegmentRbgMap;
+
+  std::vector <bool> m_ulReuse3RbgMap;
+  std::vector <bool> m_ulReuse1RbgMap;
+  std::vector <bool> m_ulPrimarySegmentRbgMap;
+  std::vector <bool> m_ulSecondarySegmentRbgMap;
+
+  enum UePosition
+  {
+    AreaUnset,
+    CenterArea,
+    EdgeArea
+  };
+
+  std::map< uint16_t, uint8_t > m_ues;
+
+  uint8_t m_rsrqThreshold;
+
+  uint8_t m_centerAreaPowerOffset;
+  uint8_t m_edgeAreaPowerOffset;
+
+  uint8_t m_centerAreaTpc;
+  uint8_t m_edgeAreaTpc;
+
+
+  uint8_t m_dlCqiThreshold;
+  /*
+  * Map of UE's DL CQI A30 received
+  */
+  std::map <uint16_t,SbMeasResult_s> m_dlCqi;
+  std::map <uint16_t, std::vector<bool> > m_dlRbgAvailableforUe;
+
+  uint8_t m_ulCqiThreshold;
+  std::map <uint16_t, std::vector<int> > m_ulCqi;
+  std::map <uint16_t, std::vector<bool> > m_ulRbAvailableforUe;
+
+  // The expected measurement identity
+  uint8_t m_measId;
+
+}; // end of class LteFfrEnhancedAlgorithm
+
+} // end of namespace ns3
+
+#endif /* LTE_FFR_ENHANCED_ALGORITHM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-rrc-sap.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,39 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+
+#include "lte-ffr-rrc-sap.h"
+
+
+namespace ns3 {
+
+
+LteFfrRrcSapProvider::~LteFfrRrcSapProvider ()
+{
+}
+
+
+LteFfrRrcSapUser::~LteFfrRrcSapUser ()
+{
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-rrc-sap.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,246 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FFR_RRC_SAP_H
+#define LTE_FFR_RRC_SAP_H
+
+#include <ns3/lte-rrc-sap.h>
+#include <ns3/epc-x2-sap.h>
+
+namespace ns3 {
+
+/**
+ * \brief Service Access Point (SAP) offered by the Frequency Reuse algorithm
+ *        instance to the eNodeB RRC instance.
+ *
+ * This is the *LteFfrRrcSapProvider*, i.e., the part of the SAP
+ * that contains the Frequency Reuse algorithm methods called by the eNodeB RRC
+ * instance.
+ */
+class LteFfrRrcSapProvider
+{
+public:
+  virtual ~LteFfrRrcSapProvider ();
+
+  /**
+   * \brief SetCellId
+   * \param cellId the Cell Identifier
+   */
+  virtual void SetCellId (uint16_t cellId ) = 0;
+
+  /**
+   * \brief Configure DL and UL bandwidth in Frequency Reuse Algorithm
+   *        function is called during Cell configuration
+   * \param ulBandwidth UL bandwidth in number of RB
+   * \param dlBandwidth DL bandwidth in number of RB
+   */
+  virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth) = 0;
+
+  /**
+   * \brief Send a UE measurement report to Frequency Reuse algorithm.
+   * \param rnti Radio Network Temporary Identity, an integer identifying the UE
+   *             where the report originates from
+   * \param measResults a single report of one measurement identity
+   *
+   * The received measurement report is a result of the UE measurement
+   * configuration previously configured by calling
+   * LteFfrRrcSapUser::AddUeMeasReportConfigForFfr. The report
+   * may be stored and utilised for the purpose of making decisions within which
+   * sub-band UE should be served.
+   */
+  virtual void ReportUeMeas (uint16_t rnti,
+                             LteRrcSap::MeasResults measResults) = 0;
+
+  /**
+   * \brief RecvLoadInformation
+   */
+  virtual void  RecvLoadInformation (EpcX2Sap::LoadInformationParams params) = 0;
+
+}; // end of class LteFfrRrcSapProvider
+
+
+/**
+ * \brief Service Access Point (SAP) offered by the eNodeB RRC instance to the
+ *        Frequency Reuse algorithm instance.
+ *
+ * This is the *LteFfrRrcSapUser*, i.e., the part of the SAP that
+ * contains the eNodeB RRC methods called by the Frequency Reuse algorithm instance.
+ */
+class LteFfrRrcSapUser
+{
+public:
+  virtual ~LteFfrRrcSapUser ();
+
+  /**
+   * \brief Request a certain reporting configuration to be fulfilled by the UEs
+   *        attached to the eNodeB entity.
+   * \param reportConfig the UE measurement reporting configuration
+   * \return the measurement identity associated with this newly added
+   *         reporting configuration
+   *
+   * The eNodeB RRC entity is expected to configure the same reporting
+   * configuration in each of the attached UEs. When later in the simulation a
+   * UE measurement report is received from a UE as a result of this
+   * configuration, the eNodeB RRC entity shall forward this report to the
+   * Frequency Reuse algorithm through the LteFfrRrcSapProvider::ReportUeMeas
+   * SAP function.
+   *
+   * \note This function is only valid before the simulation begins.
+   */
+  virtual uint8_t AddUeMeasReportConfigForFfr (LteRrcSap::ReportConfigEutra reportConfig) = 0;
+
+  /**
+   * \brief Instruct the eNodeB RRC entity to perform RrcConnectionReconfiguration
+   *        to inform UE about new PdschConfigDedicated (i.e. P_a value).
+   *        Also Downlink Power Allocation is done based on this value.
+   * \param rnti Radio Network Temporary Identity, an integer identifying the
+   *             UE which shall perform the handover
+   * \param pdschConfigDedicated new PdschConfigDedicated to be configured for UE
+   *
+   * This function is used by the Frequency Reuse algorithm entity when it decides
+   * that PDSCH for this UE should be allocated with different transmit power.
+   *
+   * The process to produce the decision is up to the implementation of Frequency Reuse
+   * algorithm. It is typically based on the reported UE measurements, which are
+   * received through the LteFfrRrcSapProvider::ReportUeMeas function.
+   */
+  virtual void SetPdschConfigDedicated (uint16_t rnti, LteRrcSap::PdschConfigDedicated pdschConfigDedicated) = 0;
+
+  /**
+   * \brief SendLoadInformation
+   */
+  virtual void  SendLoadInformation (EpcX2Sap::LoadInformationParams params) = 0;
+
+}; // end of class LteFfrRrcSapUser
+
+
+/**
+ * \brief Template for the implementation of the LteFfrRrcSapProvider
+ *        as a member of an owner class of type C to which all methods are
+ *        forwarded.
+ */
+template <class C>
+class MemberLteFfrRrcSapProvider : public LteFfrRrcSapProvider
+{
+public:
+  MemberLteFfrRrcSapProvider (C* owner);
+
+  // inherited from LteHandoverManagemenrSapProvider
+  virtual void SetCellId (uint16_t cellId );
+  virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
+  virtual void ReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void RecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+  MemberLteFfrRrcSapProvider ();
+  C* m_owner;
+
+}; // end of class MemberLteFfrRrcSapProvider
+
+
+template <class C>
+MemberLteFfrRrcSapProvider<C>::MemberLteFfrRrcSapProvider (C* owner)
+  : m_owner (owner)
+{
+}
+
+template <class C>
+void
+MemberLteFfrRrcSapProvider<C>::SetCellId (uint16_t cellId )
+{
+  m_owner->DoSetCellId (cellId);
+}
+
+template <class C>
+void
+MemberLteFfrRrcSapProvider<C>::SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth)
+{
+  m_owner->DoSetBandwidth (ulBandwidth, dlBandwidth);
+}
+
+template <class C>
+void
+MemberLteFfrRrcSapProvider<C>::ReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults)
+{
+  m_owner->DoReportUeMeas (rnti, measResults);
+}
+
+template <class C>
+void
+MemberLteFfrRrcSapProvider<C>::RecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  m_owner->DoRecvLoadInformation (params);
+}
+
+/**
+ * \brief Template for the implementation of the LteFfrRrcSapUser
+ *        as a member of an owner class of type C to which all methods are
+ *        forwarded.
+ */
+template <class C>
+class MemberLteFfrRrcSapUser : public LteFfrRrcSapUser
+{
+public:
+  MemberLteFfrRrcSapUser (C* owner);
+
+  // inherited from LteFfrRrcSapUser
+  virtual uint8_t AddUeMeasReportConfigForFfr (LteRrcSap::ReportConfigEutra reportConfig);
+
+  virtual void SetPdschConfigDedicated (uint16_t rnti, LteRrcSap::PdschConfigDedicated pdschConfigDedicated);
+
+  virtual void  SendLoadInformation (EpcX2Sap::LoadInformationParams params);
+private:
+  MemberLteFfrRrcSapUser ();
+  C* m_owner;
+
+}; // end of class LteFfrRrcSapUser
+
+template <class C>
+MemberLteFfrRrcSapUser<C>::MemberLteFfrRrcSapUser (C* owner)
+  : m_owner (owner)
+{
+}
+
+template <class C>
+uint8_t
+MemberLteFfrRrcSapUser<C>::AddUeMeasReportConfigForFfr (LteRrcSap::ReportConfigEutra reportConfig)
+{
+  return m_owner->DoAddUeMeasReportConfigForFfr (reportConfig);
+}
+
+template <class C>
+void
+MemberLteFfrRrcSapUser<C>::SetPdschConfigDedicated (uint16_t rnti, LteRrcSap::PdschConfigDedicated pdschConfigDedicated)
+{
+  m_owner->DoSetPdschConfigDedicated (rnti, pdschConfigDedicated);
+}
+
+template <class C>
+void
+MemberLteFfrRrcSapUser<C>::SendLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  m_owner->DoSendLoadInformation (params);
+}
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FFR_RRC_SAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-sap.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,38 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-ffr-sap.h"
+
+
+namespace ns3 {
+
+
+LteFfrSapProvider::~LteFfrSapProvider ()
+{
+}
+
+
+LteFfrSapUser::~LteFfrSapUser ()
+{
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-sap.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,265 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FFR_SAP_H
+#define LTE_FFR_SAP_H
+
+#include <ns3/lte-rrc-sap.h>
+#include <ns3/ff-mac-sched-sap.h>
+#include <map>
+
+namespace ns3 {
+
+/**
+ * \brief Service Access Point (SAP) offered by the Frequency Reuse algorithm
+ *        instance to the MAC Scheduler instance.
+ *
+ * This is the *LteFfrSapProvider*, i.e., the part of the SAP
+ * that contains the Frequency Reuse algorithm methods called by the MAC Scheduler
+ * instance.
+ */
+class LteFfrSapProvider
+{
+public:
+  virtual ~LteFfrSapProvider ();
+
+  /**
+    * \brief Get vector of available RBG in DL for this Cell
+    * \return vector of size (m_dlBandwidth/RbgSize); false indicates
+    *                   that RBG is free to use, true otherwise
+    *
+    * This function is called by MAC Scheduler in the beginning of DL
+    * scheduling process. Frequency Reuse Algorithm based on its policy
+    * generates vector of RBG which can be used and which can not be used
+    * by Scheduler to schedule transmission.
+    */
+  virtual std::vector <bool> GetAvailableDlRbg () = 0;
+
+  /**
+   * \brief Check if UE can be served on i-th RB in DL
+   * \param i RBG ID
+   * \param rnti Radio Network Temporary Identity, an integer identifying the UE
+   *             where the report originates from
+   * \return true if UE can be served on i-th RB, false otherwise
+   *
+   * This function is called by MAC Scheduler during DL scheduling process
+   * to check if UE is allowed to be served with i-th RBG. Frequency Reuse
+   * Algorithm based on its policy decides if RBG is allowed to UE.
+   * If yes, Scheduler will try to allocate this RBG for UE, if not this UE
+   * will not be served with this RBG.
+   */
+  virtual bool IsDlRbgAvailableForUe (int i, uint16_t rnti) = 0;
+
+  /**
+   * \brief Get vector of available RB in UL for this Cell
+   * \return vector of size m_ulBandwidth; false indicates
+   *                    that RB is free to use, true otherwise
+   *
+   * This function is called by MAC Scheduler in the beginning of UL
+   * scheduling process. Frequency Reuse Algorithm based on its policy
+   * generates vector of RB which can be used and which can not be used
+   * by Scheduler to schedule transmission.
+   */
+  virtual std::vector <bool> GetAvailableUlRbg () = 0;
+
+  /**
+   * \brief Check if UE can be served on i-th RB in UL
+   * \param i RB ID
+   * \param rnti Radio Network Temporary Identity, an integer identifying the UE
+   *             where the report originates from
+   * \return true if UE can be served on i-th RB, false otherwise
+   *
+   * This function is called by MAC Scheduler during UL scheduling process
+   * to check if UE is allowed to be served with i-th RB. Frequency Reuse
+   * Algorithm based on its policy decides if RB is allowed to UE.
+   * If yes, Scheduler will try to allocate this RB for UE, if not this UE
+   * will not be served with this RB.
+   */
+  virtual bool IsUlRbgAvailableForUe (int i, uint16_t rnti) = 0;
+
+  /**
+   * \brief ReportDlCqiInfo
+   */
+  virtual void ReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params) = 0;
+
+  /**
+   * \brief ReportUlCqiInfo
+   */
+  virtual void ReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params) = 0;
+
+  /**
+   * \brief ReportUlCqiInfo
+   */
+  virtual void ReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap ) = 0;
+
+  /**
+   * \brief GetTpc
+   */
+  virtual uint8_t GetTpc (uint16_t rnti) = 0;
+
+  /**
+   * \brief GetMinContinuousUlBandwidth
+   */
+  virtual uint8_t GetMinContinuousUlBandwidth () = 0;
+}; // end of class LteFfrSapProvider
+
+
+/**
+ * \brief Service Access Point (SAP) offered by the eNodeB RRC instance to the
+ *        Frequency Reuse algorithm instance.
+ *
+ * This is the *LteFfrSapUser*, i.e., the part of the SAP that
+ * contains the MAC Scheduler methods called by the Frequency Reuse algorithm instance.
+ */
+class LteFfrSapUser
+{
+public:
+  virtual ~LteFfrSapUser ();
+
+}; // end of class LteFfrSapUser
+
+
+/**
+ * \brief Template for the implementation of the LteFfrSapProvider
+ *        as a member of an owner class of type C to which all methods are
+ *        forwarded.
+ */
+template <class C>
+class MemberLteFfrSapProvider : public LteFfrSapProvider
+{
+public:
+  MemberLteFfrSapProvider (C* owner);
+
+  // inherited from LteFfrSapProvider
+  virtual std::vector <bool> GetAvailableDlRbg ();
+  virtual bool IsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> GetAvailableUlRbg ();
+  virtual bool IsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void ReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void ReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void ReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t GetTpc (uint16_t rnti);
+  virtual uint8_t GetMinContinuousUlBandwidth ();
+private:
+  MemberLteFfrSapProvider ();
+  C* m_owner;
+
+}; // end of class MemberLteFfrSapProvider
+
+
+template <class C>
+MemberLteFfrSapProvider<C>::MemberLteFfrSapProvider (C* owner)
+  : m_owner (owner)
+{
+}
+
+
+template <class C>
+std::vector <bool>
+MemberLteFfrSapProvider<C>::GetAvailableDlRbg ()
+{
+  return m_owner->DoGetAvailableDlRbg ();
+}
+
+template <class C>
+bool
+MemberLteFfrSapProvider<C>::IsDlRbgAvailableForUe (int i, uint16_t rnti)
+{
+  return m_owner->DoIsDlRbgAvailableForUe (i,rnti);
+}
+
+template <class C>
+std::vector <bool>
+MemberLteFfrSapProvider<C>::GetAvailableUlRbg ()
+{
+  return m_owner->DoGetAvailableUlRbg ();
+}
+
+template <class C>
+bool
+MemberLteFfrSapProvider<C>::IsUlRbgAvailableForUe (int i, uint16_t rnti)
+{
+  return m_owner->DoIsUlRbgAvailableForUe (i,rnti);
+}
+
+template <class C>
+void
+MemberLteFfrSapProvider<C>::ReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  m_owner->DoReportDlCqiInfo (params);
+}
+
+template <class C>
+void
+MemberLteFfrSapProvider<C>::ReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  m_owner->DoReportUlCqiInfo (params);
+}
+
+template <class C>
+void
+MemberLteFfrSapProvider<C>::ReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap )
+{
+  m_owner->DoReportUlCqiInfo (ulCqiMap);
+}
+
+template <class C>
+uint8_t
+MemberLteFfrSapProvider<C>::GetTpc ( uint16_t rnti )
+{
+  return m_owner->DoGetTpc (rnti);
+}
+
+template <class C>
+uint8_t
+MemberLteFfrSapProvider<C>::GetMinContinuousUlBandwidth ()
+{
+  return m_owner->DoGetMinContinuousUlBandwidth ();
+}
+
+/**
+ * \brief Template for the implementation of the LteFfrSapUser
+ *        as a member of an owner class of type C to which all methods are
+ *        forwarded.
+ */
+template <class C>
+class MemberLteFfrSapUser : public LteFfrSapUser
+{
+public:
+  MemberLteFfrSapUser (C* owner);
+
+  // inherited from LteFfrSapUser
+private:
+  MemberLteFfrSapUser ();
+  C* m_owner;
+
+}; // end of class LteFfrSapUser
+
+template <class C>
+MemberLteFfrSapUser<C>::MemberLteFfrSapUser (C* owner)
+  : m_owner (owner)
+{
+}
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FFR_SAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-soft-algorithm.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,693 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-ffr-soft-algorithm.h"
+#include <ns3/log.h>
+#include "ns3/boolean.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteFfrSoftAlgorithm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteFfrSoftAlgorithm);
+
+static const struct FfrSoftDownlinkDefaultConfiguration
+{
+  uint8_t cellId;
+  uint8_t dlBandwidth;
+  uint8_t dlCommonSubBandwidth;
+  uint8_t dlEgdeSubBandOffset;
+  uint8_t dlEdgeSubBandwidth;
+} g_ffrSoftDownlinkDefaultConfiguration[] = {
+  { 1, 15, 2, 0, 4},
+  { 2, 15, 2, 4, 4},
+  { 3, 15, 2, 8, 4},
+  { 1, 25, 6, 0, 6},
+  { 2, 25, 6, 6, 6},
+  { 3, 25, 6, 12, 6},
+  { 1, 50, 21, 0, 9},
+  { 2, 50, 21, 9, 9},
+  { 3, 50, 21, 18, 11},
+  { 1, 75, 36, 0, 12},
+  { 2, 75, 36, 12, 12},
+  { 3, 75, 36, 24, 15},
+  { 1, 100, 28, 0, 24},
+  { 2, 100, 28, 24, 24},
+  { 3, 100, 28, 48, 24}
+};
+
+static const struct FfrSoftUplinkDefaultConfiguration
+{
+  uint8_t cellId;
+  uint8_t ulBandwidth;
+  uint8_t ulCommonSubBandwidth;
+  uint8_t ulEgdeSubBandOffset;
+  uint8_t ulEdgeSubBandwidth;
+} g_ffrSoftUplinkDefaultConfiguration[] = {
+  { 1, 15, 3, 0, 4},
+  { 2, 15, 3, 4, 4},
+  { 3, 15, 3, 8, 4},
+  { 1, 25, 6, 0, 6},
+  { 2, 25, 6, 6, 6},
+  { 3, 25, 6, 12, 6},
+  { 1, 50, 21, 0, 9},
+  { 2, 50, 21, 9, 9},
+  { 3, 50, 21, 18, 11},
+  { 1, 75, 36, 0, 12},
+  { 2, 75, 36, 12, 12},
+  { 3, 75, 36, 24, 15},
+  { 1, 100, 28, 0, 24},
+  { 2, 100, 28, 24, 24},
+  { 3, 100, 28, 48, 24}
+};
+
+const uint16_t NUM_DOWNLINK_CONFS (sizeof (g_ffrSoftDownlinkDefaultConfiguration) / sizeof (FfrSoftDownlinkDefaultConfiguration));
+const uint16_t NUM_UPLINK_CONFS (sizeof (g_ffrSoftUplinkDefaultConfiguration) / sizeof (FfrSoftUplinkDefaultConfiguration));
+
+
+LteFfrSoftAlgorithm::LteFfrSoftAlgorithm ()
+  : m_ffrSapUser (0),
+    m_ffrRrcSapUser (0),
+    m_dlEgdeSubBandOffset (0),
+    m_dlEdgeSubBandwidth (0),
+    m_ulEgdeSubBandOffset (0),
+    m_ulEdgeSubBandwidth (0),
+    m_measId (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_ffrSapProvider = new MemberLteFfrSapProvider<LteFfrSoftAlgorithm> (this);
+  m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFfrSoftAlgorithm> (this);
+}
+
+
+LteFfrSoftAlgorithm::~LteFfrSoftAlgorithm ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteFfrSoftAlgorithm::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ffrSapProvider;
+  delete m_ffrRrcSapProvider;
+}
+
+
+TypeId
+LteFfrSoftAlgorithm::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFfrSoftAlgorithm")
+    .SetParent<LteFfrAlgorithm> ()
+    .AddConstructor<LteFfrSoftAlgorithm> ()
+    .AddAttribute ("UlCommonSubBandwidth",
+                   "Uplink Medium (Common) SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (6),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_ulCommonSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlEdgeSubBandOffset",
+                   "Uplink Edge SubBand Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_ulEgdeSubBandOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlEdgeSubBandwidth",
+                   "Uplink Edge SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (6),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_ulEdgeSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlCommonSubBandwidth",
+                   "Downlink Medium (Common) SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (6),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_dlCommonSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlEdgeSubBandOffset",
+                   "Downlink Edge SubBand Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_dlEgdeSubBandOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlEdgeSubBandwidth",
+                   "Downlink Edge SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_dlEdgeSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterRsrqThreshold",
+                   "If the RSRQ of is worse than this threshold, UE should be served in Medium sub-band",
+                   UintegerValue (30),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_centerSubBandThreshold),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeRsrqThreshold",
+                   "If the RSRQ of is worse than this threshold, UE should be served in Edge sub-band",
+                   UintegerValue (20),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_egdeSubBandThreshold),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterAreaPowerOffset",
+                   "PdschConfigDedicated::Pa value for Center Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_centerAreaPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("MediumAreaPowerOffset",
+                   "PdschConfigDedicated::Pa value for Medium Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_mediumAreaPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeAreaPowerOffset",
+                   "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_edgeAreaPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in center area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_centerAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("MediumAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in medium area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_mediumAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in edge area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFfrSoftAlgorithm::m_edgeAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+  ;
+  return tid;
+}
+
+
+void
+LteFfrSoftAlgorithm::SetLteFfrSapUser (LteFfrSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrSapUser = s;
+}
+
+
+LteFfrSapProvider*
+LteFfrSoftAlgorithm::GetLteFfrSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrSapProvider;
+}
+
+void
+LteFfrSoftAlgorithm::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapUser = s;
+}
+
+
+LteFfrRrcSapProvider*
+LteFfrSoftAlgorithm::GetLteFfrRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapProvider;
+}
+
+
+void
+LteFfrSoftAlgorithm::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+  LteFfrAlgorithm::DoInitialize ();
+
+  NS_ASSERT_MSG (m_dlBandwidth > 14,"DlBandwidth must be at least 15 to use FFR algorithms");
+  NS_ASSERT_MSG (m_ulBandwidth > 14,"UlBandwidth must be at least 15 to use FFR algorithms");
+
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+
+  NS_LOG_LOGIC (this << " requesting Event A1 measurements"
+                     << " (threshold = 0" << ")");
+  LteRrcSap::ReportConfigEutra reportConfig;
+  reportConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
+  reportConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
+  reportConfig.threshold1.range = 0;
+  reportConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
+  reportConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS120;
+  m_measId = m_ffrRrcSapUser->AddUeMeasReportConfigForFfr (reportConfig);
+}
+
+void
+LteFfrSoftAlgorithm::Reconfigure ()
+{
+  NS_LOG_FUNCTION (this);
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+  InitializeDownlinkRbgMaps ();
+  InitializeUplinkRbgMaps ();
+  m_needReconfiguration = false;
+}
+
+void
+LteFfrSoftAlgorithm::SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_DOWNLINK_CONFS; ++i)
+    {
+      if ((g_ffrSoftDownlinkDefaultConfiguration[i].cellId == cellId)
+          && g_ffrSoftDownlinkDefaultConfiguration[i].dlBandwidth == m_dlBandwidth)
+        {
+          m_dlCommonSubBandwidth = g_ffrSoftDownlinkDefaultConfiguration[i].dlCommonSubBandwidth;
+          m_dlEgdeSubBandOffset = g_ffrSoftDownlinkDefaultConfiguration[i].dlEgdeSubBandOffset;
+          m_dlEdgeSubBandwidth = g_ffrSoftDownlinkDefaultConfiguration[i].dlEdgeSubBandwidth;
+        }
+    }
+}
+
+void
+LteFfrSoftAlgorithm::SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_UPLINK_CONFS; ++i)
+    {
+      if ((g_ffrSoftUplinkDefaultConfiguration[i].cellId == cellId)
+          && g_ffrSoftUplinkDefaultConfiguration[i].ulBandwidth == m_ulBandwidth)
+        {
+          m_ulCommonSubBandwidth = g_ffrSoftUplinkDefaultConfiguration[i].ulCommonSubBandwidth;
+          m_ulEgdeSubBandOffset = g_ffrSoftUplinkDefaultConfiguration[i].ulEgdeSubBandOffset;
+          m_ulEdgeSubBandwidth = g_ffrSoftUplinkDefaultConfiguration[i].ulEdgeSubBandwidth;
+        }
+    }
+}
+
+void
+LteFfrSoftAlgorithm::InitializeDownlinkRbgMaps ()
+{
+  m_dlRbgMap.clear ();
+  m_dlCenterRbgMap.clear ();
+  m_dlMediumRbgMap.clear ();
+  m_dlEdgeRbgMap.clear ();
+
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  m_dlRbgMap.resize (m_dlBandwidth / rbgSize, false);
+  m_dlCenterRbgMap.resize (m_dlBandwidth / rbgSize, true);
+  m_dlMediumRbgMap.resize (m_dlBandwidth / rbgSize, false);
+  m_dlEdgeRbgMap.resize (m_dlBandwidth / rbgSize, false);
+
+  NS_ASSERT_MSG (m_dlCommonSubBandwidth <= m_dlBandwidth,"DlCommonSubBandwidth higher than DlBandwidth");
+  NS_ASSERT_MSG (m_dlCommonSubBandwidth + m_dlEgdeSubBandOffset <= m_dlBandwidth,
+                 "DlCommonSubBandwidth + DlEgdeSubBandOffset higher than DlBandwidth");
+  NS_ASSERT_MSG (m_dlEgdeSubBandOffset <= m_dlBandwidth,"DlEgdeSubBandOffset higher than DlBandwidth");
+  NS_ASSERT_MSG (m_dlEdgeSubBandwidth <= m_dlBandwidth,"DlEdgeSubBandwidth higher than DlBandwidth");
+  NS_ASSERT_MSG ((m_dlCommonSubBandwidth + m_dlEgdeSubBandOffset + m_dlEdgeSubBandwidth) <= m_dlBandwidth,
+                 "(DlCommonSubBandwidth + DlEgdeSubBandOffset+DlEdgeSubBandwidth) higher than DlBandwidth");
+
+  for (uint8_t i = 0;
+       i < m_dlCommonSubBandwidth / rbgSize; i++)
+    {
+      m_dlMediumRbgMap[i] = true;
+      m_dlCenterRbgMap[i] = false;
+    }
+
+  for (uint8_t i = (m_dlCommonSubBandwidth + m_dlEgdeSubBandOffset) / rbgSize;
+       i < (m_dlCommonSubBandwidth + m_dlEgdeSubBandOffset + m_dlEdgeSubBandwidth) / rbgSize; i++)
+    {
+      m_dlEdgeRbgMap[i] = true;
+      m_dlCenterRbgMap[i] = false;
+    }
+}
+
+
+void
+LteFfrSoftAlgorithm::InitializeUplinkRbgMaps ()
+{
+  m_ulRbgMap.clear ();
+  m_ulCenterRbgMap.clear ();
+  m_ulMediumRbgMap.clear ();
+  m_ulEdgeRbgMap.clear ();
+
+  m_ulRbgMap.resize (m_ulBandwidth, false);
+  m_ulCenterRbgMap.resize (m_ulBandwidth, true);
+  m_ulMediumRbgMap.resize (m_ulBandwidth, false);
+  m_ulEdgeRbgMap.resize (m_ulBandwidth, false);
+
+  NS_ASSERT_MSG (m_ulCommonSubBandwidth <= m_ulBandwidth,"UlCommonSubBandwidth higher than UlBandwidth");
+  NS_ASSERT_MSG (m_ulCommonSubBandwidth + m_ulEgdeSubBandOffset <= m_ulBandwidth,
+                 "UlCommonSubBandwidth + UlEgdeSubBandOffset higher than UlBandwidth");
+  NS_ASSERT_MSG (m_ulEgdeSubBandOffset <= m_ulBandwidth,"UlEgdeSubBandOffset higher than UlBandwidth");
+  NS_ASSERT_MSG (m_ulEdgeSubBandwidth <= m_ulBandwidth,"UlEdgeSubBandwidth higher than UlBandwidth");
+  NS_ASSERT_MSG ((m_ulCommonSubBandwidth + m_ulEgdeSubBandOffset + m_ulEdgeSubBandwidth) <= m_ulBandwidth,
+                 "(UlCommonSubBandwidth + UlEgdeSubBandOffset+UlEdgeSubBandwidth) higher than UlBandwidth");
+
+  for (uint8_t i = 0;
+       i < m_ulCommonSubBandwidth; i++)
+    {
+      m_ulMediumRbgMap[i] = true;
+      m_ulCenterRbgMap[i] = false;
+    }
+
+  for (uint8_t i = (m_ulCommonSubBandwidth + m_ulEgdeSubBandOffset);
+       i < (m_ulCommonSubBandwidth + m_ulEgdeSubBandOffset + m_ulEdgeSubBandwidth); i++)
+    {
+      m_ulEdgeRbgMap[i] = true;
+      m_ulCenterRbgMap[i] = false;
+    }
+}
+
+std::vector <bool>
+LteFfrSoftAlgorithm::DoGetAvailableDlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_needReconfiguration)
+    {
+      Reconfigure ();
+    }
+
+  if (m_dlRbgMap.empty ())
+    {
+      InitializeDownlinkRbgMaps ();
+    }
+
+  return m_dlRbgMap;
+}
+
+bool
+LteFfrSoftAlgorithm::DoIsDlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  bool isCenterRbg = m_dlCenterRbgMap[rbgId];
+  bool isMediumRbg = m_dlMediumRbgMap[rbgId];
+  bool isEdgeRbg   = m_dlEdgeRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+    }
+
+  it = m_ues.find (rnti);
+
+  //if UE area is unknown, serve UE in medium (common) RBGs
+  if (it->second == AreaUnset)
+    {
+      return isMediumRbg;
+    }
+
+
+  bool isCenterUe = false;
+  bool isMediumUe = false;
+  bool isEdgeUe   = false;
+
+  if (it->second == CenterArea )
+    {
+      isCenterUe = true;
+    }
+  else if (it->second == MediumArea)
+    {
+      isMediumUe = true;
+    }
+  else if (it->second == EdgeArea)
+    {
+      isEdgeUe = true;
+    }
+
+  return (isCenterRbg && isCenterUe) || (isMediumRbg && isMediumUe) || (isEdgeRbg && isEdgeUe);
+}
+
+std::vector <bool>
+LteFfrSoftAlgorithm::DoGetAvailableUlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_ulRbgMap.empty ())
+    {
+      InitializeUplinkRbgMaps ();
+    }
+
+  return m_ulRbgMap;
+}
+
+bool
+LteFfrSoftAlgorithm::DoIsUlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return true;
+    }
+
+  bool isCenterRbg = m_ulCenterRbgMap[rbgId];
+  bool isMediumRbg = m_ulMediumRbgMap[rbgId];
+  bool isEdgeRbg   = m_ulEdgeRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+    }
+
+  it = m_ues.find (rnti);
+
+  //if UE area is unknown, serve UE in medium (common) RBGs
+  if (it->second == AreaUnset)
+    {
+      return isMediumRbg;
+    }
+
+
+  bool isCenterUe = false;
+  bool isMediumUe = false;
+  bool isEdgeUe   = false;
+
+  if (it->second == CenterArea )
+    {
+      isCenterUe = true;
+    }
+  else if (it->second == MediumArea)
+    {
+      isMediumUe = true;
+    }
+  else if (it->second == EdgeArea)
+    {
+      isEdgeUe = true;
+    }
+
+  return (isCenterRbg && isCenterUe) || (isMediumRbg && isMediumUe) || (isEdgeRbg && isEdgeUe);
+}
+
+void
+LteFfrSoftAlgorithm::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFfrSoftAlgorithm::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFfrSoftAlgorithm::DoReportUlCqiInfo (std::map <uint16_t, std::vector <double> > ulCqiMap)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+uint8_t
+LteFfrSoftAlgorithm::DoGetTpc (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return 1;     // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
+    }
+
+  //TS36.213 Table 5.1.1.1-2
+  //   TPC   |   Accumulated Mode  |  Absolute Mode
+  //------------------------------------------------
+  //    0    |         -1          |      -4
+  //    1    |          0          |      -1
+  //    2    |          1          |       1
+  //    3    |          3          |       4
+  //------------------------------------------------
+  // here Absolute mode is used
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      return 1;
+    }
+
+  if (it->second == CenterArea )
+    {
+      return m_centerAreaTpc;
+    }
+  else if (it->second == MediumArea)
+    {
+      return m_mediumAreaTpc;
+    }
+  else if (it->second == EdgeArea)
+    {
+      return m_edgeAreaTpc;
+    }
+
+  return 1;
+}
+
+uint8_t
+LteFfrSoftAlgorithm::DoGetMinContinuousUlBandwidth ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return m_ulBandwidth;
+    }
+
+  uint8_t centerSubBandwidth = 0;
+  uint8_t mediumSubBandwidth = 0;
+  uint8_t edgeSubBandwidth = 0;
+
+  for (uint8_t i = 0; i < m_ulCenterRbgMap.size (); i++)
+    {
+      if ( m_ulCenterRbgMap[i] == true)
+        {
+          centerSubBandwidth++;
+        }
+    }
+
+  for (uint8_t i = 0; i < m_ulMediumRbgMap.size (); i++)
+    {
+      if ( m_ulMediumRbgMap[i] == true)
+        {
+          mediumSubBandwidth++;
+        }
+    }
+
+  for (uint8_t i = 0; i < m_ulEdgeRbgMap.size (); i++)
+    {
+      if ( m_ulEdgeRbgMap[i] == true)
+        {
+          edgeSubBandwidth++;
+        }
+    }
+
+  uint8_t minContinuousUlBandwidth = m_ulBandwidth;
+
+  minContinuousUlBandwidth =
+    ((centerSubBandwidth > 0 ) && (centerSubBandwidth < minContinuousUlBandwidth)) ? centerSubBandwidth : minContinuousUlBandwidth;
+
+  minContinuousUlBandwidth =
+    ((mediumSubBandwidth > 0 ) && (mediumSubBandwidth < minContinuousUlBandwidth)) ? mediumSubBandwidth : minContinuousUlBandwidth;
+
+  minContinuousUlBandwidth =
+    ((edgeSubBandwidth > 0 ) && (edgeSubBandwidth < minContinuousUlBandwidth)) ? edgeSubBandwidth : minContinuousUlBandwidth;
+
+  NS_LOG_INFO ("minContinuousUlBandwidth: " << (int)minContinuousUlBandwidth);
+
+  return minContinuousUlBandwidth;
+}
+
+void
+LteFfrSoftAlgorithm::DoReportUeMeas (uint16_t rnti,
+                                     LteRrcSap::MeasResults measResults)
+{
+  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
+  NS_LOG_INFO ("RNTI :" << rnti << " MeasId: " << (uint16_t) measResults.measId
+                        << " RSRP: " << (uint16_t)measResults.rsrpResult
+                        << " RSRQ: " << (uint16_t)measResults.rsrqResult);
+
+  NS_ASSERT_MSG (m_centerSubBandThreshold >= m_egdeSubBandThreshold,
+                 "CenterSubBandThreshold must be higher than EgdeSubBandThreshold");
+
+  if (measResults.measId != m_measId)
+    {
+      NS_LOG_WARN ("Ignoring measId " << (uint16_t) measResults.measId);
+    }
+  else
+    {
+
+      std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+      if (it == m_ues.end ())
+        {
+          m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+        }
+
+      it = m_ues.find (rnti);
+      if (measResults.rsrqResult >= m_centerSubBandThreshold)
+        {
+          if (it->second != CenterArea)
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Center sub-band");
+              it->second = CenterArea;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_centerAreaPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+      else if (measResults.rsrqResult < m_egdeSubBandThreshold)
+        {
+          if (it->second != EdgeArea )
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Edge sub-band");
+              it->second = EdgeArea;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_edgeAreaPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+      else
+        {
+          if (it->second != MediumArea)
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Medium sub-band");
+              it->second = MediumArea;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_mediumAreaPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+    }
+}
+
+void
+LteFfrSoftAlgorithm::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ffr-soft-algorithm.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,148 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FFR_SOFT_ALGORITHM_H
+#define LTE_FFR_SOFT_ALGORITHM_H
+
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-ffr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
+#include <ns3/lte-rrc-sap.h>
+#include <map>
+
+namespace ns3 {
+
+
+/**
+ * \brief Soft Fractional Frequency Reuse algorithm implementation
+ */
+class LteFfrSoftAlgorithm : public LteFfrAlgorithm
+{
+public:
+  /**
+   * \brief Creates a trivial ffr algorithm instance.
+   */
+  LteFfrSoftAlgorithm ();
+
+  virtual ~LteFfrSoftAlgorithm ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  // inherited from LteFfrAlgorithm
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s);
+  virtual LteFfrSapProvider* GetLteFfrSapProvider ();
+
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s);
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider ();
+
+  // let the forwarder class access the protected and private members
+  friend class MemberLteFfrSapProvider<LteFfrSoftAlgorithm>;
+  friend class MemberLteFfrRrcSapProvider<LteFfrSoftAlgorithm>;
+
+protected:
+  // inherited from Object
+  virtual void DoInitialize ();
+  virtual void DoDispose ();
+
+  virtual void Reconfigure ();
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+  virtual std::vector <bool> DoGetAvailableDlRbg ();
+  virtual bool DoIsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> DoGetAvailableUlRbg ();
+  virtual bool DoIsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t DoGetTpc (uint16_t rnti);
+  virtual uint8_t DoGetMinContinuousUlBandwidth ();
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+  void SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void InitializeDownlinkRbgMaps ();
+  void InitializeUplinkRbgMaps ();
+
+
+  // FFR SAP
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
+
+  // FFR RRF SAP
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
+  uint8_t m_dlCommonSubBandwidth;
+  uint8_t m_dlEgdeSubBandOffset;
+  uint8_t m_dlEdgeSubBandwidth;
+
+  uint8_t m_ulCommonSubBandwidth;
+  uint8_t m_ulEgdeSubBandOffset;
+  uint8_t m_ulEdgeSubBandwidth;
+
+  std::vector <bool> m_dlRbgMap;
+  std::vector <bool> m_ulRbgMap;
+
+  std::vector <bool> m_dlCenterRbgMap;
+  std::vector <bool> m_ulCenterRbgMap;
+
+  std::vector <bool> m_dlMediumRbgMap;
+  std::vector <bool> m_ulMediumRbgMap;
+
+  std::vector <bool> m_dlEdgeRbgMap;
+  std::vector <bool> m_ulEdgeRbgMap;
+
+  enum UePosition
+  {
+    AreaUnset,
+    CenterArea,
+    MediumArea,
+    EdgeArea
+  };
+
+  std::map< uint16_t, uint8_t > m_ues;
+
+  uint8_t m_centerSubBandThreshold;
+  uint8_t m_egdeSubBandThreshold;
+
+  uint8_t m_centerAreaPowerOffset;
+  uint8_t m_mediumAreaPowerOffset;
+  uint8_t m_edgeAreaPowerOffset;
+
+  uint8_t m_centerAreaTpc;
+  uint8_t m_mediumAreaTpc;
+  uint8_t m_edgeAreaTpc;
+
+  // The expected measurement identity
+  uint8_t m_measId;
+
+}; // end of class LteFfrSoftAlgorithm
+
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FFR_SOFT_ALGORITHM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-fr-hard-algorithm.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,385 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-fr-hard-algorithm.h"
+#include <ns3/log.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteFrHardAlgorithm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteFrHardAlgorithm);
+
+static const struct FrHardDownlinkDefaultConfiguration
+{
+  uint8_t m_cellId;
+  uint8_t m_dlBandwidth;
+  uint8_t m_dlOffset;
+  uint8_t m_dlSubBand;
+} g_frHardDownlinkDefaultConfiguration[] = {
+  { 1, 15, 0, 4},
+  { 2, 15, 4, 4},
+  { 3, 15, 8, 6},
+  { 1, 25, 0, 8},
+  { 2, 25, 8, 8},
+  { 3, 25, 16, 9},
+  { 1, 50, 0, 16},
+  { 2, 50, 16, 16},
+  { 3, 50, 32, 18},
+  { 1, 75, 0, 24},
+  { 2, 75, 24, 24},
+  { 3, 75, 48, 27},
+  { 1, 100, 0, 32},
+  { 2, 100, 32, 32},
+  { 3, 100, 64, 36}
+};
+
+static const struct FrHardUplinkDefaultConfiguration
+{
+  uint8_t m_cellId;
+  uint8_t m_ulBandwidth;
+  uint8_t m_ulOffset;
+  uint8_t m_ulSubBand;
+} g_frHardUplinkDefaultConfiguration[] = {
+  { 1, 15, 0, 5},
+  { 2, 15, 5, 5},
+  { 3, 15, 10, 5},
+  { 1, 25, 0, 8},
+  { 2, 25, 8, 8},
+  { 3, 25, 16, 9},
+  { 1, 50, 0, 16},
+  { 2, 50, 16, 16},
+  { 3, 50, 32, 18},
+  { 1, 75, 0, 24},
+  { 2, 75, 24, 24},
+  { 3, 75, 48, 27},
+  { 1, 100, 0, 32},
+  { 2, 100, 32, 32},
+  { 3, 100, 64, 36}
+};
+
+const uint16_t NUM_DOWNLINK_CONFS (sizeof (g_frHardDownlinkDefaultConfiguration) / sizeof (FrHardDownlinkDefaultConfiguration));
+const uint16_t NUM_UPLINK_CONFS (sizeof (g_frHardUplinkDefaultConfiguration) / sizeof (FrHardUplinkDefaultConfiguration));
+
+LteFrHardAlgorithm::LteFrHardAlgorithm ()
+  : m_ffrSapUser (0),
+    m_ffrRrcSapUser (0),
+    m_dlOffset (0),
+    m_dlSubBand (0),
+    m_ulOffset (0),
+    m_ulSubBand (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_ffrSapProvider = new MemberLteFfrSapProvider<LteFrHardAlgorithm> (this);
+  m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFrHardAlgorithm> (this);
+}
+
+
+LteFrHardAlgorithm::~LteFrHardAlgorithm ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteFrHardAlgorithm::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ffrSapProvider;
+  delete m_ffrRrcSapProvider;
+}
+
+
+TypeId
+LteFrHardAlgorithm::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFrHardAlgorithm")
+    .SetParent<LteFfrAlgorithm> ()
+    .AddConstructor<LteFrHardAlgorithm> ()
+    .AddAttribute ("UlSubBandOffset",
+                   "Uplink Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrHardAlgorithm::m_ulOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlSubBandwidth",
+                   "Uplink Transmission SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (25),
+                   MakeUintegerAccessor (&LteFrHardAlgorithm::m_ulSubBand),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlSubBandOffset",
+                   "Downlink Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrHardAlgorithm::m_dlOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlSubBandwidth",
+                   "Downlink Transmission SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (25),
+                   MakeUintegerAccessor (&LteFrHardAlgorithm::m_dlSubBand),
+                   MakeUintegerChecker<uint8_t> ())
+  ;
+  return tid;
+}
+
+
+void
+LteFrHardAlgorithm::SetLteFfrSapUser (LteFfrSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrSapUser = s;
+}
+
+
+LteFfrSapProvider*
+LteFrHardAlgorithm::GetLteFfrSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrSapProvider;
+}
+
+void
+LteFrHardAlgorithm::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapUser = s;
+}
+
+
+LteFfrRrcSapProvider*
+LteFrHardAlgorithm::GetLteFfrRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapProvider;
+}
+
+
+void
+LteFrHardAlgorithm::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+  LteFfrAlgorithm::DoInitialize ();
+
+  NS_ASSERT_MSG (m_dlBandwidth > 14,"DlBandwidth must be at least 15 to use FFR algorithms");
+  NS_ASSERT_MSG (m_ulBandwidth > 14,"UlBandwidth must be at least 15 to use FFR algorithms");
+
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+
+}
+
+void
+LteFrHardAlgorithm::Reconfigure ()
+{
+  NS_LOG_FUNCTION (this);
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+  InitializeDownlinkRbgMaps ();
+  InitializeUplinkRbgMaps ();
+  m_needReconfiguration = false;
+}
+
+void
+LteFrHardAlgorithm::SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_DOWNLINK_CONFS; ++i)
+    {
+      if ((g_frHardDownlinkDefaultConfiguration[i].m_cellId == cellId)
+          && g_frHardDownlinkDefaultConfiguration[i].m_dlBandwidth == m_dlBandwidth)
+        {
+          m_dlOffset = g_frHardDownlinkDefaultConfiguration[i].m_dlOffset;
+          m_dlSubBand = g_frHardDownlinkDefaultConfiguration[i].m_dlSubBand;
+        }
+    }
+}
+
+void
+LteFrHardAlgorithm::SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_UPLINK_CONFS; ++i)
+    {
+      if ((g_frHardUplinkDefaultConfiguration[i].m_cellId == cellId)
+          && g_frHardUplinkDefaultConfiguration[i].m_ulBandwidth == m_ulBandwidth)
+        {
+          m_ulOffset = g_frHardUplinkDefaultConfiguration[i].m_ulOffset;
+          m_ulSubBand = g_frHardUplinkDefaultConfiguration[i].m_ulSubBand;
+        }
+    }
+}
+
+void
+LteFrHardAlgorithm::InitializeDownlinkRbgMaps ()
+{
+  m_dlRbgMap.clear ();
+
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  m_dlRbgMap.resize (m_dlBandwidth / rbgSize, true);
+
+  NS_ASSERT_MSG (m_dlOffset <= m_dlBandwidth,"DlOffset higher than DlBandwidth");
+  NS_ASSERT_MSG (m_dlSubBand <= m_dlBandwidth,"DlBandwidth higher than DlBandwidth");
+  NS_ASSERT_MSG ((m_dlOffset + m_dlSubBand) <= m_dlBandwidth,
+                 "(DlOffset+DlSubBand) higher than DlBandwidth");
+
+  for (uint8_t i = m_dlOffset / rbgSize; i < (m_dlOffset / rbgSize + m_dlSubBand / rbgSize); i++)
+    {
+      m_dlRbgMap[i] = false;
+
+    }
+}
+
+void
+LteFrHardAlgorithm::InitializeUplinkRbgMaps ()
+{
+  m_ulRbgMap.clear ();
+
+  if (!m_enabledInUplink)
+    {
+      m_ulRbgMap.resize (m_ulBandwidth, false);
+      return;
+    }
+
+  m_ulRbgMap.resize (m_ulBandwidth, true);
+
+  NS_ASSERT_MSG (m_ulOffset <= m_ulBandwidth,"UlOffset higher than UlBandwidth");
+  NS_ASSERT_MSG (m_ulSubBand <= m_ulBandwidth,"UlBandwidth higher than UlBandwidth");
+  NS_ASSERT_MSG ((m_ulOffset + m_ulSubBand) <= m_ulBandwidth,
+                 "(UlOffset+UlSubBand) higher than UlBandwidth");
+
+  for (uint8_t i = m_ulOffset; i < (m_ulOffset + m_ulSubBand); i++)
+    {
+      m_ulRbgMap[i] = false;
+    }
+}
+
+std::vector <bool>
+LteFrHardAlgorithm::DoGetAvailableDlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_needReconfiguration)
+    {
+      Reconfigure ();
+    }
+
+  if (m_dlRbgMap.empty ())
+    {
+      InitializeDownlinkRbgMaps ();
+    }
+
+  return m_dlRbgMap;
+}
+
+bool
+LteFrHardAlgorithm::DoIsDlRbgAvailableForUe (int rbId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  return !m_dlRbgMap[rbId];
+}
+
+std::vector <bool>
+LteFrHardAlgorithm::DoGetAvailableUlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_ulRbgMap.empty ())
+    {
+      InitializeUplinkRbgMaps ();
+    }
+
+  return m_ulRbgMap;
+}
+
+bool
+LteFrHardAlgorithm::DoIsUlRbgAvailableForUe (int rbId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return true;
+    }
+
+  return !m_ulRbgMap[rbId];
+}
+
+void
+LteFrHardAlgorithm::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrHardAlgorithm::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrHardAlgorithm::DoReportUlCqiInfo (std::map <uint16_t, std::vector <double> > ulCqiMap)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+uint8_t
+LteFrHardAlgorithm::DoGetTpc (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  return 1; // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
+}
+
+uint8_t
+LteFrHardAlgorithm::DoGetMinContinuousUlBandwidth ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return m_ulBandwidth;
+    }
+
+  return m_ulSubBand;
+}
+
+void
+LteFrHardAlgorithm::DoReportUeMeas (uint16_t rnti,
+                                    LteRrcSap::MeasResults measResults)
+{
+  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrHardAlgorithm::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-fr-hard-algorithm.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,111 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FR_HARD_ALGORITHM_H
+#define LTE_FR_HARD_ALGORITHM_H
+
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-ffr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
+#include <ns3/lte-rrc-sap.h>
+
+namespace ns3 {
+
+
+/**
+ * \brief Hard Frequency Reuse algorithm implementation which uses only 1 sub-band.
+ */
+class LteFrHardAlgorithm : public LteFfrAlgorithm
+{
+public:
+  /**
+   * \brief Creates a trivial ffr algorithm instance.
+   */
+  LteFrHardAlgorithm ();
+
+  virtual ~LteFrHardAlgorithm ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  // inherited from LteFfrAlgorithm
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s);
+  virtual LteFfrSapProvider* GetLteFfrSapProvider ();
+
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s);
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider ();
+
+  // let the forwarder class access the protected and private members
+  friend class MemberLteFfrSapProvider<LteFrHardAlgorithm>;
+  friend class MemberLteFfrRrcSapProvider<LteFrHardAlgorithm>;
+
+protected:
+  // inherited from Object
+  virtual void DoInitialize ();
+  virtual void DoDispose ();
+
+  virtual void Reconfigure ();
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+  virtual std::vector <bool> DoGetAvailableDlRbg ();
+  virtual bool DoIsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> DoGetAvailableUlRbg ();
+  virtual bool DoIsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t DoGetTpc (uint16_t rnti);
+  virtual uint8_t DoGetMinContinuousUlBandwidth ();
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+  void SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void InitializeDownlinkRbgMaps ();
+  void InitializeUplinkRbgMaps ();
+
+  // FFR SAP
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
+
+  // FFR RRF SAP
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
+  uint8_t m_dlOffset;
+  uint8_t m_dlSubBand;
+
+  uint8_t m_ulOffset;
+  uint8_t m_ulSubBand;
+
+  std::vector <bool> m_dlRbgMap;
+  std::vector <bool> m_ulRbgMap;
+
+}; // end of class LteFrHardAlgorithm
+
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FR_HARD_ALGORITHM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-fr-no-op-algorithm.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,194 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-fr-no-op-algorithm.h"
+#include <ns3/log.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteFrNoOpAlgorithm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteFrNoOpAlgorithm);
+
+
+LteFrNoOpAlgorithm::LteFrNoOpAlgorithm ()
+  : m_ffrSapUser (0), m_ffrRrcSapUser (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_ffrSapProvider = new MemberLteFfrSapProvider<LteFrNoOpAlgorithm> (this);
+  m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFrNoOpAlgorithm> (this);
+}
+
+
+LteFrNoOpAlgorithm::~LteFrNoOpAlgorithm ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteFrNoOpAlgorithm::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ffrSapProvider;
+  delete m_ffrRrcSapProvider;
+}
+
+
+TypeId
+LteFrNoOpAlgorithm::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFrNoOpAlgorithm")
+    .SetParent<LteFfrAlgorithm> ()
+    .AddConstructor<LteFrNoOpAlgorithm> ()
+  ;
+  return tid;
+}
+
+
+void
+LteFrNoOpAlgorithm::SetLteFfrSapUser (LteFfrSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrSapUser = s;
+}
+
+
+LteFfrSapProvider*
+LteFrNoOpAlgorithm::GetLteFfrSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrSapProvider;
+}
+
+void
+LteFrNoOpAlgorithm::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapUser = s;
+}
+
+
+LteFfrRrcSapProvider*
+LteFrNoOpAlgorithm::GetLteFfrRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapProvider;
+}
+
+
+void
+LteFrNoOpAlgorithm::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+  LteFfrAlgorithm::DoInitialize ();
+}
+
+void
+LteFrNoOpAlgorithm::Reconfigure ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+std::vector <bool>
+LteFrNoOpAlgorithm::DoGetAvailableDlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+  std::vector <bool> rbgMap;
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  rbgMap.resize (m_dlBandwidth/rbgSize, false);
+  return rbgMap;
+}
+
+bool
+LteFrNoOpAlgorithm::DoIsDlRbgAvailableForUe (int i, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  return true;
+}
+
+std::vector <bool>
+LteFrNoOpAlgorithm::DoGetAvailableUlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+  std::vector <bool> rbgMap;
+  rbgMap.resize (m_ulBandwidth, false);
+  return rbgMap;
+}
+
+bool
+LteFrNoOpAlgorithm::DoIsUlRbgAvailableForUe (int i, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  return true;
+}
+
+void
+LteFrNoOpAlgorithm::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrNoOpAlgorithm::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrNoOpAlgorithm::DoReportUlCqiInfo (std::map <uint16_t, std::vector <double> > ulCqiMap)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+uint8_t
+LteFrNoOpAlgorithm::DoGetTpc (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  return 1; // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
+}
+
+uint8_t
+LteFrNoOpAlgorithm::DoGetMinContinuousUlBandwidth ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ulBandwidth;
+}
+
+void
+LteFrNoOpAlgorithm::DoReportUeMeas (uint16_t rnti,
+                                    LteRrcSap::MeasResults measResults)
+{
+  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrNoOpAlgorithm::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-fr-no-op-algorithm.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,103 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FR_NO_OP_ALGORITHM_H
+#define LTE_FR_NO_OP_ALGORITHM_H
+
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-ffr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
+#include <ns3/lte-rrc-sap.h>
+
+namespace ns3 {
+
+
+/**
+ * \brief FR algorithm implementation which simply does nothing.
+ *
+ * Selecting this FR algorithm is equivalent to disabling FFR.
+ * This is the default choice.
+ *
+ * To enable FR, please select another FR algorithm, i.e.,
+ * another child class of LteFfrAlgorithm.
+ */
+class LteFrNoOpAlgorithm : public LteFfrAlgorithm
+{
+public:
+  /**
+   * \brief Creates a NoOP FR algorithm instance.
+   */
+  LteFrNoOpAlgorithm ();
+
+  virtual ~LteFrNoOpAlgorithm ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  // inherited from LteFfrAlgorithm
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s);
+  virtual LteFfrSapProvider* GetLteFfrSapProvider ();
+
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s);
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider ();
+
+  // let the forwarder class access the protected and private members
+  friend class MemberLteFfrSapProvider<LteFrNoOpAlgorithm>;
+  friend class MemberLteFfrRrcSapProvider<LteFrNoOpAlgorithm>;
+
+protected:
+  // inherited from Object
+  virtual void DoInitialize ();
+  virtual void DoDispose ();
+
+  virtual void Reconfigure ();
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+  virtual std::vector <bool> DoGetAvailableDlRbg ();
+  virtual bool DoIsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> DoGetAvailableUlRbg ();
+  virtual bool DoIsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t DoGetTpc (uint16_t rnti);
+  virtual uint8_t DoGetMinContinuousUlBandwidth ();
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+  // FFR SAP
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
+
+  // FFR RRF SAP
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
+}; // end of class LteFrNoOpAlgorithm
+
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FFR_NO_OP_ALGORITHM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-fr-soft-algorithm.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,559 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-fr-soft-algorithm.h"
+#include <ns3/log.h>
+#include "ns3/boolean.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteFrSoftAlgorithm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteFrSoftAlgorithm);
+
+static const struct FrSoftDownlinkDefaultConfiguration
+{
+  uint8_t cellId;
+  uint8_t dlBandwidth;
+  uint8_t dlEgdeSubBandOffset;
+  uint8_t dlEdgeSubBandwidth;
+} g_frSoftDownlinkDefaultConfiguration[] = {
+  { 1, 15, 0, 4},
+  { 2, 15, 4, 4},
+  { 3, 15, 8, 6},
+  { 1, 25, 0, 8},
+  { 2, 25, 8, 8},
+  { 3, 25, 16, 9},
+  { 1, 50, 0, 16},
+  { 2, 50, 16, 16},
+  { 3, 50, 32, 18},
+  { 1, 75, 0, 24},
+  { 2, 75, 24, 24},
+  { 3, 75, 48, 27},
+  { 1, 100, 0, 32},
+  { 2, 100, 32, 32},
+  { 3, 100, 64, 36}
+};
+
+static const struct FrSoftUplinkDefaultConfiguration
+{
+  uint8_t cellId;
+  uint8_t ulBandwidth;
+  uint8_t ulEgdeSubBandOffset;
+  uint8_t ulEdgeSubBandwidth;
+} g_frSoftUplinkDefaultConfiguration[] = {
+  { 1, 15, 0, 5},
+  { 2, 15, 5, 5},
+  { 3, 15, 10, 5},
+  { 1, 25, 0, 8},
+  { 2, 25, 8, 8},
+  { 3, 25, 16, 9},
+  { 1, 50, 0, 16},
+  { 2, 50, 16, 16},
+  { 3, 50, 32, 18},
+  { 1, 75, 0, 24},
+  { 2, 75, 24, 24},
+  { 3, 75, 48, 27},
+  { 1, 100, 0, 32},
+  { 2, 100, 32, 32},
+  { 3, 100, 64, 36}
+};
+
+const uint16_t NUM_DOWNLINK_CONFS (sizeof (g_frSoftDownlinkDefaultConfiguration) / sizeof (FrSoftDownlinkDefaultConfiguration));
+const uint16_t NUM_UPLINK_CONFS (sizeof (g_frSoftUplinkDefaultConfiguration) / sizeof (FrSoftUplinkDefaultConfiguration));
+
+
+LteFrSoftAlgorithm::LteFrSoftAlgorithm ()
+  : m_ffrSapUser (0),
+    m_ffrRrcSapUser (0),
+    m_dlEgdeSubBandOffset (0),
+    m_dlEdgeSubBandwidth (0),
+    m_ulEgdeSubBandOffset (0),
+    m_ulEdgeSubBandwidth (0),
+    m_measId (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_ffrSapProvider = new MemberLteFfrSapProvider<LteFrSoftAlgorithm> (this);
+  m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFrSoftAlgorithm> (this);
+}
+
+
+LteFrSoftAlgorithm::~LteFrSoftAlgorithm ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteFrSoftAlgorithm::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ffrSapProvider;
+  delete m_ffrRrcSapProvider;
+}
+
+
+TypeId
+LteFrSoftAlgorithm::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFrSoftAlgorithm")
+    .SetParent<LteFfrAlgorithm> ()
+    .AddConstructor<LteFrSoftAlgorithm> ()
+    .AddAttribute ("UlEdgeSubBandOffset",
+                   "Uplink Edge SubBand Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_ulEgdeSubBandOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlEdgeSubBandwidth",
+                   "Uplink Edge SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_ulEdgeSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlEdgeSubBandOffset",
+                   "Downlink Edge SubBand Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_dlEgdeSubBandOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlEdgeSubBandwidth",
+                   "Downlink Edge SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_dlEdgeSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("AllowCenterUeUseEdgeSubBand",
+                   "If true center UEs can receive on Edge SubBand RBGs",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&LteFrSoftAlgorithm::m_isEdgeSubBandForCenterUe),
+                   MakeBooleanChecker ())
+    .AddAttribute ("RsrqThreshold",
+                   "If the RSRQ of is worse than this threshold, UE should be served in Edge sub-band",
+                   UintegerValue (20),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_egdeSubBandThreshold),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterPowerOffset",
+                   "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_centerPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgePowerOffset",
+                   "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_edgePowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in center area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_centerAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in edge area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFrSoftAlgorithm::m_edgeAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+  ;
+  return tid;
+}
+
+
+void
+LteFrSoftAlgorithm::SetLteFfrSapUser (LteFfrSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrSapUser = s;
+}
+
+
+LteFfrSapProvider*
+LteFrSoftAlgorithm::GetLteFfrSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrSapProvider;
+}
+
+void
+LteFrSoftAlgorithm::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapUser = s;
+}
+
+
+LteFfrRrcSapProvider*
+LteFrSoftAlgorithm::GetLteFfrRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapProvider;
+}
+
+
+void
+LteFrSoftAlgorithm::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+  LteFfrAlgorithm::DoInitialize ();
+
+  NS_ASSERT_MSG (m_dlBandwidth > 14,"DlBandwidth must be at least 15 to use FFR algorithms");
+  NS_ASSERT_MSG (m_ulBandwidth > 14,"UlBandwidth must be at least 15 to use FFR algorithms");
+
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+
+  NS_LOG_LOGIC (this << " requesting Event A1 measurements"
+                     << " (threshold = 0" << ")");
+  LteRrcSap::ReportConfigEutra reportConfig;
+  reportConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
+  reportConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
+  reportConfig.threshold1.range = 0;
+  reportConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
+  reportConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS120;
+  m_measId = m_ffrRrcSapUser->AddUeMeasReportConfigForFfr (reportConfig);
+}
+
+void
+LteFrSoftAlgorithm::Reconfigure ()
+{
+  NS_LOG_FUNCTION (this);
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+  InitializeDownlinkRbgMaps ();
+  InitializeUplinkRbgMaps ();
+  m_needReconfiguration = false;
+}
+
+void
+LteFrSoftAlgorithm::SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_DOWNLINK_CONFS; ++i)
+    {
+      if ((g_frSoftDownlinkDefaultConfiguration[i].cellId == cellId)
+          && g_frSoftDownlinkDefaultConfiguration[i].dlBandwidth == m_dlBandwidth)
+        {
+          m_dlEgdeSubBandOffset = g_frSoftDownlinkDefaultConfiguration[i].dlEgdeSubBandOffset;
+          m_dlEdgeSubBandwidth = g_frSoftDownlinkDefaultConfiguration[i].dlEdgeSubBandwidth;
+        }
+    }
+}
+
+void
+LteFrSoftAlgorithm::SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_UPLINK_CONFS; ++i)
+    {
+      if ((g_frSoftUplinkDefaultConfiguration[i].cellId == cellId)
+          && g_frSoftUplinkDefaultConfiguration[i].ulBandwidth == m_ulBandwidth)
+        {
+          m_ulEgdeSubBandOffset = g_frSoftUplinkDefaultConfiguration[i].ulEgdeSubBandOffset;
+          m_ulEdgeSubBandwidth = g_frSoftUplinkDefaultConfiguration[i].ulEdgeSubBandwidth;
+        }
+    }
+}
+
+void
+LteFrSoftAlgorithm::InitializeDownlinkRbgMaps ()
+{
+  m_dlRbgMap.clear ();
+  m_dlEdgeRbgMap.clear ();
+
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  m_dlRbgMap.resize (m_dlBandwidth / rbgSize, false);
+  m_dlEdgeRbgMap.resize (m_dlBandwidth / rbgSize, false);
+
+  NS_ASSERT_MSG (m_dlEgdeSubBandOffset <= m_dlBandwidth,"DlEgdeSubBandOffset higher than DlBandwidth");
+  NS_ASSERT_MSG (m_dlEdgeSubBandwidth <= m_dlBandwidth,"DlEdgeSubBandwidth higher than DlBandwidth");
+  NS_ASSERT_MSG ((m_dlEgdeSubBandOffset + m_dlEdgeSubBandwidth) <= m_dlBandwidth,
+                 "(DlEgdeSubBandOffset+DlEdgeSubBandwidth) higher than DlBandwidth");
+
+  for (uint8_t i = m_dlEgdeSubBandOffset / rbgSize;
+       i < (m_dlEgdeSubBandOffset + m_dlEdgeSubBandwidth) / rbgSize; i++)
+    {
+      m_dlEdgeRbgMap[i] = true;
+    }
+}
+
+void
+LteFrSoftAlgorithm::InitializeUplinkRbgMaps ()
+{
+  m_ulRbgMap.clear ();
+  m_ulEdgeRbgMap.clear ();
+
+  m_ulRbgMap.resize (m_ulBandwidth, false);
+  m_ulEdgeRbgMap.resize (m_ulBandwidth, false);
+
+  NS_ASSERT_MSG (m_ulEgdeSubBandOffset <= m_dlBandwidth,"UlEgdeSubBandOffset higher than DlBandwidth");
+  NS_ASSERT_MSG (m_ulEdgeSubBandwidth <= m_dlBandwidth,"UlEdgeSubBandwidth higher than DlBandwidth");
+  NS_ASSERT_MSG ((m_ulEgdeSubBandOffset + m_ulEdgeSubBandwidth) <= m_dlBandwidth,
+                 "(UlEgdeSubBandOffset+UlEdgeSubBandwidth) higher than DlBandwidth");
+
+  for (uint8_t i = m_ulEgdeSubBandOffset; i < (m_ulEgdeSubBandOffset + m_ulEdgeSubBandwidth); i++)
+    {
+      m_ulEdgeRbgMap[i] = true;
+    }
+}
+
+std::vector <bool>
+LteFrSoftAlgorithm::DoGetAvailableDlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_needReconfiguration)
+    {
+      Reconfigure ();
+    }
+
+  if (m_dlRbgMap.empty ())
+    {
+      InitializeDownlinkRbgMaps ();
+    }
+
+  return m_dlRbgMap;
+}
+
+bool
+LteFrSoftAlgorithm::DoIsDlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  bool edgeRbg = m_dlEdgeRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+      return !edgeRbg;
+    }
+
+  bool edgeUe = false;
+  if (it->second == CellEdge )
+    {
+      edgeUe = true;
+    }
+
+  if (!edgeUe && m_isEdgeSubBandForCenterUe)
+    {
+      return true;
+    }
+
+  return (edgeRbg && edgeUe) || (!edgeRbg && !edgeUe);
+}
+
+std::vector <bool>
+LteFrSoftAlgorithm::DoGetAvailableUlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_ulRbgMap.empty ())
+    {
+      InitializeUplinkRbgMaps ();
+    }
+
+  return m_ulRbgMap;
+}
+
+bool
+LteFrSoftAlgorithm::DoIsUlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return true;
+    }
+
+  bool edgeRbg = m_ulEdgeRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+      return !edgeRbg;
+    }
+
+  bool edgeUe = false;
+  if (it->second == CellEdge )
+    {
+      edgeUe = true;
+    }
+
+  if (!edgeUe && m_isEdgeSubBandForCenterUe)
+    {
+      return true;
+    }
+
+  return (edgeRbg && edgeUe) || (!edgeRbg && !edgeUe);
+}
+
+void
+LteFrSoftAlgorithm::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrSoftAlgorithm::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrSoftAlgorithm::DoReportUlCqiInfo (std::map <uint16_t, std::vector <double> > ulCqiMap)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+uint8_t
+LteFrSoftAlgorithm::DoGetTpc (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return 1;     // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
+    }
+
+  //TS36.213 Table 5.1.1.1-2
+  //   TPC   |   Accumulated Mode  |  Absolute Mode
+  //------------------------------------------------
+  //    0    |         -1          |      -4
+  //    1    |          0          |      -1
+  //    2    |          1          |       1
+  //    3    |          3          |       4
+  //------------------------------------------------
+  // here Absolute mode is used
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      return 1;
+    }
+
+  if (it->second == CellEdge )
+    {
+      return m_edgeAreaTpc;
+    }
+  else if (it->second == CellCenter )
+    {
+      return m_centerAreaTpc;
+    }
+
+  return 1;
+}
+
+uint8_t
+LteFrSoftAlgorithm::DoGetMinContinuousUlBandwidth ()
+{
+  NS_LOG_FUNCTION (this);
+
+  uint8_t minContinuousUlBandwidth = m_ulBandwidth;
+
+  if (!m_enabledInUplink)
+    {
+      return minContinuousUlBandwidth;
+    }
+
+  uint8_t leftBandwidth = m_ulEgdeSubBandOffset;
+  uint8_t centerBandwidth = m_ulEdgeSubBandwidth;
+  uint8_t rightBandwidth = m_ulBandwidth - m_ulEdgeSubBandwidth - m_ulEgdeSubBandOffset;
+
+  minContinuousUlBandwidth =
+    ((leftBandwidth > 0 ) && (leftBandwidth < minContinuousUlBandwidth)) ? leftBandwidth : minContinuousUlBandwidth;
+
+  minContinuousUlBandwidth =
+    ((centerBandwidth > 0 ) && (centerBandwidth < minContinuousUlBandwidth)) ? centerBandwidth : minContinuousUlBandwidth;
+
+  minContinuousUlBandwidth =
+    ((rightBandwidth > 0 ) && (rightBandwidth < minContinuousUlBandwidth)) ? rightBandwidth : minContinuousUlBandwidth;
+
+  NS_LOG_INFO ("minContinuousUlBandwidth: " << (int)minContinuousUlBandwidth);
+
+  return minContinuousUlBandwidth;
+}
+
+void
+LteFrSoftAlgorithm::DoReportUeMeas (uint16_t rnti,
+                                    LteRrcSap::MeasResults measResults)
+{
+  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
+  NS_LOG_INFO ("RNTI :" << rnti << " MeasId: " << (uint16_t) measResults.measId
+                        << " RSRP: " << (uint16_t)measResults.rsrpResult
+                        << " RSRQ: " << (uint16_t)measResults.rsrqResult);
+
+  if (measResults.measId != m_measId)
+    {
+      NS_LOG_WARN ("Ignoring measId " << (uint16_t) measResults.measId);
+    }
+  else
+    {
+      std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+      if (it == m_ues.end ())
+        {
+          m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+        }
+      it = m_ues.find (rnti);
+
+      if (measResults.rsrqResult < m_egdeSubBandThreshold)
+        {
+          if (it->second != CellEdge)
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Edge sub-band");
+              it->second = CellEdge;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_edgePowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+      else
+        {
+          if (it->second != CellCenter)
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Center sub-band");
+              it->second = CellCenter;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_centerPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+    }
+}
+
+void
+LteFrSoftAlgorithm::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-fr-soft-algorithm.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,138 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FR_SOFT_ALGORITHM_H
+#define LTE_FR_SOFT_ALGORITHM_H
+
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-ffr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
+#include <ns3/lte-rrc-sap.h>
+#include <map>
+
+namespace ns3 {
+
+
+/**
+ * \brief Soft Frequency Reuse algorithm implementation
+ */
+class LteFrSoftAlgorithm : public LteFfrAlgorithm
+{
+public:
+  /**
+   * \brief Creates a trivial ffr algorithm instance.
+   */
+  LteFrSoftAlgorithm ();
+
+  virtual ~LteFrSoftAlgorithm ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  // inherited from LteFfrAlgorithm
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s);
+  virtual LteFfrSapProvider* GetLteFfrSapProvider ();
+
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s);
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider ();
+
+  // let the forwarder class access the protected and private members
+  friend class MemberLteFfrSapProvider<LteFrSoftAlgorithm>;
+  friend class MemberLteFfrRrcSapProvider<LteFrSoftAlgorithm>;
+
+protected:
+  // inherited from Object
+  virtual void DoInitialize ();
+  virtual void DoDispose ();
+
+  virtual void Reconfigure ();
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+  virtual std::vector <bool> DoGetAvailableDlRbg ();
+  virtual bool DoIsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> DoGetAvailableUlRbg ();
+  virtual bool DoIsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t DoGetTpc (uint16_t rnti);
+  virtual uint8_t DoGetMinContinuousUlBandwidth ();
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+  void SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void InitializeDownlinkRbgMaps ();
+  void InitializeUplinkRbgMaps ();
+
+  // FFR SAP
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
+
+  // FFR RRF SAP
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
+  bool m_isEdgeSubBandForCenterUe;
+
+  uint8_t m_dlEgdeSubBandOffset;
+  uint8_t m_dlEdgeSubBandwidth;
+
+  uint8_t m_ulEgdeSubBandOffset;
+  uint8_t m_ulEdgeSubBandwidth;
+
+  std::vector <bool> m_dlRbgMap;
+  std::vector <bool> m_ulRbgMap;
+
+  std::vector <bool> m_dlEdgeRbgMap;
+  std::vector <bool> m_ulEdgeRbgMap;
+
+  enum SubBand
+  {
+    AreaUnset,
+    CellCenter,
+    CellEdge
+  };
+
+  std::map< uint16_t, uint8_t > m_ues;
+  std::vector<uint16_t> m_egdeUes;
+
+  uint8_t m_egdeSubBandThreshold;
+
+  uint8_t m_centerPowerOffset;
+  uint8_t m_edgePowerOffset;
+
+  uint8_t m_centerAreaTpc;
+  uint8_t m_edgeAreaTpc;
+
+  // The expected measurement identity
+  uint8_t m_measId;
+
+}; // end of class LteFrSoftAlgorithm
+
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FR_SOFT_ALGORITHM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-fr-strict-algorithm.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,571 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-fr-strict-algorithm.h"
+#include <ns3/log.h>
+#include "ns3/boolean.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteFrStrictAlgorithm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteFrStrictAlgorithm);
+
+static const struct FrStrictDownlinkDefaultConfiguration
+{
+  uint8_t cellId;
+  uint8_t dlBandwidth;
+  uint8_t dlCommonSubBandwidth;
+  uint8_t dlEgdeSubBandOffset;
+  uint8_t dlEdgeSubBandwidth;
+} g_frStrictDownlinkDefaultConfiguration[] = {
+  { 1, 15, 2, 0, 4},
+  { 2, 15, 2, 4, 4},
+  { 3, 15, 2, 8, 4},
+  { 1, 25, 6, 0, 6},
+  { 2, 25, 6, 6, 6},
+  { 3, 25, 6, 12, 6},
+  { 1, 50, 21, 0, 9},
+  { 2, 50, 21, 9, 9},
+  { 3, 50, 21, 18, 11},
+  { 1, 75, 36, 0, 12},
+  { 2, 75, 36, 12, 12},
+  { 3, 75, 36, 24, 15},
+  { 1, 100, 28, 0, 24},
+  { 2, 100, 28, 24, 24},
+  { 3, 100, 28, 48, 24}
+};
+
+static const struct FrStrictUplinkDefaultConfiguration
+{
+  uint8_t cellId;
+  uint8_t ulBandwidth;
+  uint8_t ulCommonSubBandwidth;
+  uint8_t ulEgdeSubBandOffset;
+  uint8_t ulEdgeSubBandwidth;
+} g_frStrictUplinkDefaultConfiguration[] = {
+  { 1, 15, 3, 0, 4},
+  { 2, 15, 3, 4, 4},
+  { 3, 15, 3, 8, 4},
+  { 1, 25, 6, 0, 6},
+  { 2, 25, 6, 6, 6},
+  { 3, 25, 6, 12, 6},
+  { 1, 50, 21, 0, 9},
+  { 2, 50, 21, 9, 9},
+  { 3, 50, 21, 18, 11},
+  { 1, 75, 36, 0, 12},
+  { 2, 75, 36, 12, 12},
+  { 3, 75, 36, 24, 15},
+  { 1, 100, 28, 0, 24},
+  { 2, 100, 28, 24, 24},
+  { 3, 100, 28, 48, 24}
+};
+
+const uint16_t NUM_DOWNLINK_CONFS (sizeof (g_frStrictDownlinkDefaultConfiguration) / sizeof (FrStrictDownlinkDefaultConfiguration));
+const uint16_t NUM_UPLINK_CONFS (sizeof (g_frStrictUplinkDefaultConfiguration) / sizeof (FrStrictUplinkDefaultConfiguration));
+
+
+LteFrStrictAlgorithm::LteFrStrictAlgorithm ()
+  : m_ffrSapUser (0),
+    m_ffrRrcSapUser (0),
+    m_dlEgdeSubBandOffset (0),
+    m_dlEdgeSubBandwidth (0),
+    m_ulEgdeSubBandOffset (0),
+    m_ulEdgeSubBandwidth (0),
+    m_measId (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_ffrSapProvider = new MemberLteFfrSapProvider<LteFrStrictAlgorithm> (this);
+  m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFrStrictAlgorithm> (this);
+}
+
+
+LteFrStrictAlgorithm::~LteFrStrictAlgorithm ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteFrStrictAlgorithm::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ffrSapProvider;
+  delete m_ffrRrcSapProvider;
+}
+
+
+TypeId
+LteFrStrictAlgorithm::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFrStrictAlgorithm")
+    .SetParent<LteFfrAlgorithm> ()
+    .AddConstructor<LteFrStrictAlgorithm> ()
+    .AddAttribute ("UlCommonSubBandwidth",
+                   "Uplink Common SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (25),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_ulCommonSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlEdgeSubBandOffset",
+                   "Uplink Edge SubBand Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_ulEgdeSubBandOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlEdgeSubBandwidth",
+                   "Uplink Edge SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_ulEdgeSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlCommonSubBandwidth",
+                   "Downlink Common SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (25),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_dlCommonSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlEdgeSubBandOffset",
+                   "Downlink Edge SubBand Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_dlEgdeSubBandOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlEdgeSubBandwidth",
+                   "Downlink Edge SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_dlEdgeSubBandwidth),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("RsrqThreshold",
+                   "If the RSRQ of is worse than this threshold, UE should be served in Edge sub-band",
+                   UintegerValue (20),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_egdeSubBandThreshold),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterPowerOffset",
+                   "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_centerAreaPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgePowerOffset",
+                   "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
+                   UintegerValue (5),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_edgeAreaPowerOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("CenterAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in center area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_centerAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EdgeAreaTpc",
+                   "TPC value which will be set in DL-DCI for UEs in edge area"
+                   "Absolute mode is used, default value 1 is mapped to -1 according to"
+                   "TS36.213 Table 5.1.1.1-2",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteFrStrictAlgorithm::m_edgeAreaTpc),
+                   MakeUintegerChecker<uint8_t> ())
+  ;
+  return tid;
+}
+
+
+void
+LteFrStrictAlgorithm::SetLteFfrSapUser (LteFfrSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrSapUser = s;
+}
+
+
+LteFfrSapProvider*
+LteFrStrictAlgorithm::GetLteFfrSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrSapProvider;
+}
+
+void
+LteFrStrictAlgorithm::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapUser = s;
+}
+
+
+LteFfrRrcSapProvider*
+LteFrStrictAlgorithm::GetLteFfrRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapProvider;
+}
+
+
+void
+LteFrStrictAlgorithm::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+  LteFfrAlgorithm::DoInitialize ();
+
+  NS_ASSERT_MSG (m_dlBandwidth > 14,"DlBandwidth must be at least 15 to use FFR algorithms");
+  NS_ASSERT_MSG (m_ulBandwidth > 14,"UlBandwidth must be at least 15 to use FFR algorithms");
+
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+
+  NS_LOG_LOGIC (this << " requesting Event A1 measurements"
+                     << " (threshold = 0" << ")");
+  LteRrcSap::ReportConfigEutra reportConfig;
+  reportConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
+  reportConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
+  reportConfig.threshold1.range = 0;
+  reportConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
+  reportConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS120;
+  m_measId = m_ffrRrcSapUser->AddUeMeasReportConfigForFfr (reportConfig);
+}
+
+void
+LteFrStrictAlgorithm::Reconfigure ()
+{
+  NS_LOG_FUNCTION (this);
+  if (m_frCellTypeId != 0)
+    {
+      SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
+      SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
+    }
+  InitializeDownlinkRbgMaps ();
+  InitializeUplinkRbgMaps ();
+  m_needReconfiguration = false;
+}
+
+void
+LteFrStrictAlgorithm::SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_DOWNLINK_CONFS; ++i)
+    {
+      if ((g_frStrictDownlinkDefaultConfiguration[i].cellId == cellId)
+          && g_frStrictDownlinkDefaultConfiguration[i].dlBandwidth == m_dlBandwidth)
+        {
+          m_dlCommonSubBandwidth = g_frStrictDownlinkDefaultConfiguration[i].dlCommonSubBandwidth;
+          m_dlEgdeSubBandOffset = g_frStrictDownlinkDefaultConfiguration[i].dlEgdeSubBandOffset;
+          m_dlEdgeSubBandwidth = g_frStrictDownlinkDefaultConfiguration[i].dlEdgeSubBandwidth;
+        }
+    }
+}
+
+void
+LteFrStrictAlgorithm::SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth)
+{
+  NS_LOG_FUNCTION (this);
+  for (uint16_t i = 0; i < NUM_UPLINK_CONFS; ++i)
+    {
+      if ((g_frStrictUplinkDefaultConfiguration[i].cellId == cellId)
+          && g_frStrictUplinkDefaultConfiguration[i].ulBandwidth == m_ulBandwidth)
+        {
+          m_ulCommonSubBandwidth = g_frStrictUplinkDefaultConfiguration[i].ulCommonSubBandwidth;
+          m_ulEgdeSubBandOffset = g_frStrictUplinkDefaultConfiguration[i].ulEgdeSubBandOffset;
+          m_ulEdgeSubBandwidth = g_frStrictUplinkDefaultConfiguration[i].ulEdgeSubBandwidth;
+        }
+    }
+}
+
+void
+LteFrStrictAlgorithm::InitializeDownlinkRbgMaps ()
+{
+  m_dlRbgMap.clear ();
+  m_dlEdgeRbgMap.clear ();
+
+  int rbgSize = GetRbgSize (m_dlBandwidth);
+  m_dlRbgMap.resize (m_dlBandwidth / rbgSize, true);
+  m_dlEdgeRbgMap.resize (m_dlBandwidth / rbgSize, false);
+
+  NS_ASSERT_MSG (m_dlCommonSubBandwidth <= m_dlBandwidth,"DlCommonSubBandwidth higher than DlBandwidth");
+  NS_ASSERT_MSG (m_dlEgdeSubBandOffset <= m_dlBandwidth,"DlEgdeSubBandOffset higher than DlBandwidth");
+  NS_ASSERT_MSG (m_dlEdgeSubBandwidth <= m_dlBandwidth,"DlEdgeSubBandwidth higher than DlBandwidth");
+  NS_ASSERT_MSG ((m_dlCommonSubBandwidth + m_dlEgdeSubBandOffset + m_dlEdgeSubBandwidth) <= m_dlBandwidth,
+                 "(DlCommonSubBandwidth+DlEgdeSubBandOffset+DlEdgeSubBandwidth) higher than DlBandwidth");
+
+  for (uint8_t i = 0; i < m_dlCommonSubBandwidth / rbgSize; i++)
+    {
+      m_dlRbgMap[i] = false;
+
+    }
+
+  for (uint8_t i = m_dlCommonSubBandwidth / rbgSize + m_dlEgdeSubBandOffset / rbgSize;
+       i < (m_dlCommonSubBandwidth / rbgSize + m_dlEgdeSubBandOffset / rbgSize
+            + m_dlEdgeSubBandwidth / rbgSize); i++)
+    {
+      m_dlRbgMap[i] = false;
+      m_dlEdgeRbgMap[i] = true;
+    }
+}
+
+void
+LteFrStrictAlgorithm::InitializeUplinkRbgMaps ()
+{
+  m_ulRbgMap.clear ();
+  m_ulEdgeRbgMap.clear ();
+
+  if (!m_enabledInUplink)
+    {
+      m_ulRbgMap.resize (m_ulBandwidth, false);
+      return;
+    }
+
+  m_ulRbgMap.resize (m_ulBandwidth, true);
+  m_ulEdgeRbgMap.resize (m_ulBandwidth, false);
+
+  NS_ASSERT_MSG (m_ulCommonSubBandwidth <= m_ulBandwidth,"UlCommonSubBandwidth higher than UlBandwidth");
+  NS_ASSERT_MSG (m_ulEgdeSubBandOffset <= m_ulBandwidth,"UlEgdeSubBandOffset higher than UlBandwidth");
+  NS_ASSERT_MSG (m_ulEdgeSubBandwidth <= m_ulBandwidth,"UlEdgeSubBandwidth higher than UlBandwidth");
+  NS_ASSERT_MSG ((m_ulCommonSubBandwidth + m_ulEgdeSubBandOffset + m_ulEdgeSubBandwidth) <= m_dlBandwidth,
+                 "(UlCommonSubBandwidth+UlEgdeSubBandOffset+UlEdgeSubBandwidth) higher than UlBandwidth");
+
+  for (uint8_t i = 0; i < m_ulCommonSubBandwidth; i++)
+    {
+      m_ulRbgMap[i] = false;
+
+    }
+
+  for (uint8_t i = m_ulCommonSubBandwidth + m_ulEgdeSubBandOffset;
+       i < (m_ulCommonSubBandwidth + m_ulEgdeSubBandOffset
+            + m_ulEdgeSubBandwidth); i++)
+    {
+      m_ulRbgMap[i] = false;
+      m_ulEdgeRbgMap[i] = true;
+    }
+}
+
+
+std::vector <bool>
+LteFrStrictAlgorithm::DoGetAvailableDlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_needReconfiguration)
+    {
+      Reconfigure ();
+    }
+
+  if (m_dlRbgMap.empty ())
+    {
+      InitializeDownlinkRbgMaps ();
+    }
+
+  return m_dlRbgMap;
+}
+
+bool
+LteFrStrictAlgorithm::DoIsDlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  bool edgeRbg = m_dlEdgeRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+      return !edgeRbg;
+    }
+
+  bool edgeUe = false;
+  if (it->second == CellEdge )
+    {
+      edgeUe = true;
+    }
+
+  return (edgeRbg && edgeUe) || (!edgeRbg && !edgeUe);
+}
+
+std::vector <bool>
+LteFrStrictAlgorithm::DoGetAvailableUlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_ulRbgMap.empty ())
+    {
+      InitializeUplinkRbgMaps ();
+    }
+
+  return m_ulRbgMap;
+}
+
+bool
+LteFrStrictAlgorithm::DoIsUlRbgAvailableForUe (int rbgId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return true;
+    }
+
+  bool edgeRbg = m_ulEdgeRbgMap[rbgId];
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+      return !edgeRbg;
+    }
+
+  bool edgeUe = false;
+  if (it->second == CellEdge )
+    {
+      edgeUe = true;
+    }
+
+  return (edgeRbg && edgeUe) || (!edgeRbg && !edgeUe);
+}
+
+void
+LteFrStrictAlgorithm::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrStrictAlgorithm::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+void
+LteFrStrictAlgorithm::DoReportUlCqiInfo (std::map <uint16_t, std::vector <double> > ulCqiMap)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, because it is empty");
+}
+
+uint8_t
+LteFrStrictAlgorithm::DoGetTpc (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return 1;     // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
+    }
+
+  //TS36.213 Table 5.1.1.1-2
+  //   TPC   |   Accumulated Mode  |  Absolute Mode
+  //------------------------------------------------
+  //    0    |         -1          |      -4
+  //    1    |          0          |      -1
+  //    2    |          1          |       1
+  //    3    |          3          |       4
+  //------------------------------------------------
+  // here Absolute mode is used
+
+  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+  if (it == m_ues.end ())
+    {
+      return 1;
+    }
+
+  if (it->second == CellEdge )
+    {
+      return m_edgeAreaTpc;
+    }
+  else if (it->second == CellCenter )
+    {
+      return m_centerAreaTpc;
+    }
+
+  return 1;
+}
+
+uint8_t
+LteFrStrictAlgorithm::DoGetMinContinuousUlBandwidth ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_enabledInUplink)
+    {
+      return m_ulBandwidth;
+    }
+
+  uint8_t minContinuousUlBandwidth = m_ulCommonSubBandwidth < m_ulEdgeSubBandwidth ? m_ulCommonSubBandwidth : m_ulEdgeSubBandwidth;
+  NS_LOG_INFO ("minContinuousUlBandwidth: " << (int)minContinuousUlBandwidth);
+
+  return minContinuousUlBandwidth;
+}
+
+void
+LteFrStrictAlgorithm::DoReportUeMeas (uint16_t rnti,
+                                      LteRrcSap::MeasResults measResults)
+{
+  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
+  NS_LOG_INFO ("RNTI :" << rnti << " MeasId: " << (uint16_t) measResults.measId
+                        << " RSRP: " << (uint16_t)measResults.rsrpResult
+                        << " RSRQ: " << (uint16_t)measResults.rsrqResult);
+
+  if (measResults.measId != m_measId)
+    {
+      NS_LOG_WARN ("Ignoring measId " << (uint16_t) measResults.measId);
+    }
+  else
+    {
+      std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
+      if (it == m_ues.end ())
+        {
+          m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
+        }
+      it = m_ues.find (rnti);
+
+      if (measResults.rsrqResult < m_egdeSubBandThreshold)
+        {
+          if (it->second != CellEdge )
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Edge sub-band");
+              it->second = CellEdge;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_edgeAreaPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+      else
+        {
+          if (it->second != CellCenter)
+            {
+              NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Center sub-band");
+              it->second = CellCenter;
+
+              LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+              pdschConfigDedicated.pa = m_centerAreaPowerOffset;
+              m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
+            }
+        }
+    }
+}
+
+void
+LteFrStrictAlgorithm::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_WARN ("Method should not be called, since it is empty");
+
+}
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-fr-strict-algorithm.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,139 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FR_STRICT_ALGORITHM_H
+#define LTE_FR_STRICT_ALGORITHM_H
+
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-ffr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
+#include <ns3/lte-rrc-sap.h>
+#include <map>
+
+namespace ns3 {
+
+
+/**
+ * \brief Strict Frequency Reuse algorithm implementation
+ */
+class LteFrStrictAlgorithm : public LteFfrAlgorithm
+{
+public:
+  /**
+   * \brief Creates a trivial ffr algorithm instance.
+   */
+  LteFrStrictAlgorithm ();
+
+  virtual ~LteFrStrictAlgorithm ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  // inherited from LteFfrAlgorithm
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s);
+  virtual LteFfrSapProvider* GetLteFfrSapProvider ();
+
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s);
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider ();
+
+  // let the forwarder class access the protected and private members
+  friend class MemberLteFfrSapProvider<LteFrStrictAlgorithm>;
+  friend class MemberLteFfrRrcSapProvider<LteFrStrictAlgorithm>;
+
+protected:
+  // inherited from Object
+  virtual void DoInitialize ();
+  virtual void DoDispose ();
+
+  virtual void Reconfigure ();
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+  virtual std::vector <bool> DoGetAvailableDlRbg ();
+  virtual bool DoIsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> DoGetAvailableUlRbg ();
+  virtual bool DoIsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t DoGetTpc (uint16_t rnti);
+  virtual uint8_t DoGetMinContinuousUlBandwidth ();
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+  void SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth);
+  void InitializeDownlinkRbgMaps ();
+  void InitializeUplinkRbgMaps ();
+
+  // FFR SAP
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
+
+  // FFR RRF SAP
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
+
+  uint8_t m_dlCommonSubBandwidth;
+  uint8_t m_dlEgdeSubBandOffset;
+  uint8_t m_dlEdgeSubBandwidth;
+
+  uint8_t m_ulCommonSubBandwidth;
+  uint8_t m_ulEgdeSubBandOffset;
+  uint8_t m_ulEdgeSubBandwidth;
+
+  std::vector <bool> m_dlRbgMap;
+  std::vector <bool> m_ulRbgMap;
+
+  std::vector <bool> m_dlEdgeRbgMap;
+  std::vector <bool> m_ulEdgeRbgMap;
+
+  enum SubBand
+  {
+    AreaUnset,
+    CellCenter,
+    CellEdge
+  };
+
+  std::map< uint16_t, uint8_t > m_ues;
+  std::vector<uint16_t> m_egdeUes;
+
+  uint8_t m_egdeSubBandThreshold;
+
+  uint8_t m_centerAreaPowerOffset;
+  uint8_t m_edgeAreaPowerOffset;
+
+  uint8_t m_centerAreaTpc;
+  uint8_t m_edgeAreaTpc;
+
+  // The expected measurement identity
+  uint8_t m_measId;
+
+}; // end of class LteFrStrictAlgorithm
+
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FR_STRICT_ALGORITHM_H */
--- a/src/lte/model/lte-interference.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-interference.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -20,7 +20,7 @@
 
 
 #include "lte-interference.h"
-#include "lte-sinr-chunk-processor.h"
+#include "lte-chunk-processor.h"
 
 #include <ns3/simulator.h>
 #include <ns3/log.h>
@@ -78,15 +78,15 @@
       m_rxSignal = rxPsd->Copy ();
       m_lastChangeTime = Now ();
       m_receiving = true;
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
         {
           (*it)->Start ();
         }
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
         {
           (*it)->Start ();
         }
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
         {
           (*it)->Start (); 
         }
@@ -115,15 +115,15 @@
     {
       ConditionallyEvaluateChunk ();
       m_receiving = false;
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
         {
           (*it)->End ();
         }
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
         {
           (*it)->End ();
         }
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
         {
           (*it)->End (); 
         }
@@ -192,17 +192,17 @@
 
       SpectrumValue sinr = (*m_rxSignal) / interf;
       Time duration = Now () - m_lastChangeTime;
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
         {
-          (*it)->EvaluateSinrChunk (sinr, duration);
+          (*it)->EvaluateChunk (sinr, duration);
         }
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
         {
-          (*it)->EvaluateSinrChunk (interf, duration);
+          (*it)->EvaluateChunk (interf, duration);
         }
-      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
+      for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
         {
-          (*it)->EvaluateSinrChunk (*m_rxSignal, duration);
+          (*it)->EvaluateChunk (*m_rxSignal, duration);
         }
       m_lastChangeTime = Now ();
     }
@@ -228,21 +228,21 @@
 }
 
 void
-LteInterference::AddRsPowerChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteInterference::AddRsPowerChunkProcessor (Ptr<LteChunkProcessor> p)
 {
   NS_LOG_FUNCTION (this << p);
   m_rsPowerChunkProcessorList.push_back (p);
 }
 
 void
-LteInterference::AddSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteInterference::AddSinrChunkProcessor (Ptr<LteChunkProcessor> p)
 {
   NS_LOG_FUNCTION (this << p);
   m_sinrChunkProcessorList.push_back (p);
 }
 
 void
-LteInterference::AddInterferenceChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteInterference::AddInterferenceChunkProcessor (Ptr<LteChunkProcessor> p)
 {
   NS_LOG_FUNCTION (this << p);
   m_interfChunkProcessorList.push_back (p);
--- a/src/lte/model/lte-interference.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-interference.h	Fri Sep 05 01:12:55 2014 +0200
@@ -34,7 +34,7 @@
 
 
 
-class LteSinrChunkProcessor;
+class LteChunkProcessor;
 
 
 
@@ -54,31 +54,31 @@
   virtual void DoDispose ();
 
   /**
-   * Add a LteSinrChunkProcessor that will use the time-vs-frequency SINR
+   * Add a LteChunkProcessor that will use the time-vs-frequency SINR
    * calculated by this LteInterference instance. Note that all the
-   * added LteSinrChunkProcessors will work in parallel. 
+   * added LteChunkProcessors will work in parallel.
    *
    * @param p
    */
-  void AddSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+  void AddSinrChunkProcessor (Ptr<LteChunkProcessor> p);
 
   /**
-   * Add a LteSinrChunkProcessor that will use the time-vs-frequency
+   * Add a LteChunkProcessor that will use the time-vs-frequency
    *  interference calculated by this LteInterference instance. Note 
-   *  that all the added LteSinrChunkProcessors will work in parallel.
+   *  that all the added LteChunkProcessors will work in parallel.
    *
    * @param p
    */
-  void AddInterferenceChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+  void AddInterferenceChunkProcessor (Ptr<LteChunkProcessor> p);
 
   /**
-   * Add a LteSinrChunkProcessor that will use the time-vs-frequency
+   * Add a LteChunkProcessor that will use the time-vs-frequency
    *  power calculated by this LteInterference instance. Note
-   *  that all the added LteSinrChunkProcessors will work in parallel.
+   *  that all the added LteChunkProcessors will work in parallel.
    *
    * @param p
    */
-  void AddRsPowerChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+  void AddRsPowerChunkProcessor (Ptr<LteChunkProcessor> p);
 
   /**
    * notify that the PHY is starting a RX attempt
@@ -143,15 +143,15 @@
 
   /** all the processor instances that need to be notified whenever
   a new interference chunk is calculated */
-  std::list<Ptr<LteSinrChunkProcessor> > m_rsPowerChunkProcessorList;
+  std::list<Ptr<LteChunkProcessor> > m_rsPowerChunkProcessorList;
 
   /** all the processor instances that need to be notified whenever
       a new SINR chunk is calculated */
-  std::list<Ptr<LteSinrChunkProcessor> > m_sinrChunkProcessorList;
+  std::list<Ptr<LteChunkProcessor> > m_sinrChunkProcessorList;
 
   /** all the processor instances that need to be notified whenever
       a new interference chunk is calculated */
-  std::list<Ptr<LteSinrChunkProcessor> > m_interfChunkProcessorList; 
+  std::list<Ptr<LteChunkProcessor> > m_interfChunkProcessorList;
 
 
 };
--- a/src/lte/model/lte-rrc-header.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-rrc-header.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -263,7 +263,7 @@
 {
   // Serialize PhysicalConfigDedicated Sequence
   std::bitset<10> optionalFieldsPhysicalConfigDedicated;
-  optionalFieldsPhysicalConfigDedicated.set (9,0);  // pdsch-ConfigDedicated not present
+  optionalFieldsPhysicalConfigDedicated.set (9,physicalConfigDedicated.havePdschConfigDedicated);  // pdsch-ConfigDedicated
   optionalFieldsPhysicalConfigDedicated.set (8,0);  // pucch-ConfigDedicated not present
   optionalFieldsPhysicalConfigDedicated.set (7,0);  // pusch-ConfigDedicated not present
   optionalFieldsPhysicalConfigDedicated.set (6,0);  // uplinkPowerControlDedicated not present
@@ -275,6 +275,20 @@
   optionalFieldsPhysicalConfigDedicated.set (0,0);  // schedulingRequestConfig not present
   SerializeSequence (optionalFieldsPhysicalConfigDedicated,true);
 
+  if (physicalConfigDedicated.havePdschConfigDedicated)
+    {
+      // Serialize Pdsch-ConfigDedicated Sequence:
+      // 0 optional / default fields, no extension marker.
+      SerializeSequence (std::bitset<0> (),false);
+
+      // Serialize  p-a
+      // Assuming the value in the struct is the enum index
+      SerializeEnum (8,physicalConfigDedicated.pdschConfigDedicated.pa);
+
+      // Serialize release
+      SerializeNull ();
+    }
+
   if (physicalConfigDedicated.haveSoundingRsUlConfigDedicated)
     {
       // Serialize SoundingRS-UL-ConfigDedicated choice:
@@ -2093,10 +2107,21 @@
   std::bitset<10> optionalFieldPresent;
   bIterator = DeserializeSequence (&optionalFieldPresent,true,bIterator);
 
+  physicalConfigDedicated->havePdschConfigDedicated = optionalFieldPresent[9];
   if (optionalFieldPresent[9])
     {
       // Deserialize pdsch-ConfigDedicated
-      // ...
+      std::bitset<0> bitset0;
+      bIterator = DeserializeSequence (&bitset0,false,bIterator);
+
+      int slct;
+
+      // Deserialize p-a
+      bIterator = DeserializeEnum (8,&slct,bIterator);
+      physicalConfigDedicated->pdschConfigDedicated.pa = slct;
+
+      bIterator = DeserializeNull (bIterator);
+
     }
   if (optionalFieldPresent[8])
     {
--- a/src/lte/model/lte-rrc-sap.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-rrc-sap.h	Fri Sep 05 01:12:55 2014 +0200
@@ -133,6 +133,66 @@
     uint8_t transmissionMode;
   };
 
+  struct PdschConfigCommon
+  {
+	int8_t referenceSignalPower;  // INTEGER (-60..50),
+    int8_t pb;                    // INTEGER (0..3),
+  };
+
+  struct PdschConfigDedicated
+  {
+    /*
+     * P_A values, TS 36.331 6.3.2 PDSCH-Config
+     * ENUMERATED { dB-6, dB-4dot77, dB-3, dB-1dot77, dB0, dB1, dB2, dB3 }
+     */
+    enum
+    {
+      dB_6,
+      dB_4dot77,
+      dB_3,
+      dB_1dot77,
+      dB0,
+      dB1,
+      dB2,
+      dB3
+    } value;
+    uint8_t pa;
+  };
+
+  static double ConvertPdschConfigDedicated2Double (PdschConfigDedicated pdschConfigDedicated)
+  {
+    double pa = 0;
+    switch (pdschConfigDedicated.pa)
+      {
+      case PdschConfigDedicated::dB_6:
+        pa = -6;
+        break;
+      case PdschConfigDedicated::dB_4dot77:
+        pa = -4.77;
+        break;
+      case PdschConfigDedicated::dB_3:
+        pa = -3;
+        break;
+      case PdschConfigDedicated::dB_1dot77:
+        pa = -1.77;
+        break;
+      case PdschConfigDedicated::dB0:
+        pa = 0;
+        break;
+      case PdschConfigDedicated::dB1:
+        pa = 1;
+        break;
+      case PdschConfigDedicated::dB2:
+        pa = 2;
+        break;
+      case PdschConfigDedicated::dB3:
+        pa = 3;
+        break;
+      default:
+        break;
+      }
+    return pa;
+  }
 
   struct PhysicalConfigDedicated
   {
@@ -140,6 +200,8 @@
     SoundingRsUlConfigDedicated soundingRsUlConfigDedicated;
     bool haveAntennaInfoDedicated;
     AntennaInfoDedicated antennaInfo;
+    bool havePdschConfigDedicated;
+    PdschConfigDedicated pdschConfigDedicated;
   };
 
 
@@ -183,6 +245,7 @@
   struct RadioResourceConfigCommonSib
   {
     RachConfigCommon rachConfigCommon;
+    PdschConfigCommon pdschConfigCommon;
   };
 
   struct RadioResourceConfigDedicated
--- a/src/lte/model/lte-sinr-chunk-processor.cc	Thu Sep 04 23:13:41 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2010 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Nicola Baldo <nbaldo@cttc.es>
- * Modified by : Marco Miozzo <mmiozzo@cttc.es>
- *        (move from CQI to Ctrl and Data SINR Chunk processors
- */
-
-
-#include <ns3/log.h>
-
-#include "lte-sinr-chunk-processor.h"
-
-NS_LOG_COMPONENT_DEFINE ("LteSinrChunkProcessor");
-
-namespace ns3 {
-
-LteSinrChunkProcessor::~LteSinrChunkProcessor ()
-{
-  NS_LOG_FUNCTION (this);
-}
-
-
-// ------------- LteCtrlSinrChunkProcessor ------------------------------
-
-LteCtrlSinrChunkProcessor::LteCtrlSinrChunkProcessor (Ptr<LtePhy> p)
-  : m_phy (p),
-  m_spectrumPhy (0)
-{
-  NS_LOG_FUNCTION (this << p);
-  NS_ASSERT (m_phy);
-}
-
-LteCtrlSinrChunkProcessor::LteCtrlSinrChunkProcessor (Ptr<LtePhy> p, Ptr<LteSpectrumPhy> s)
-: m_phy (p),
-  m_spectrumPhy (s)
-{
-  NS_LOG_FUNCTION (this << p);
-  NS_ASSERT (m_phy);
-  NS_ASSERT (m_spectrumPhy);
-}
-
-
-LteCtrlSinrChunkProcessor::~LteCtrlSinrChunkProcessor ()
-{
-  NS_LOG_FUNCTION (this);
-}
-
-
-void 
-LteCtrlSinrChunkProcessor::Start ()
-{
-  NS_LOG_FUNCTION (this);
-  m_sumSinr = 0;
-  m_totDuration = MicroSeconds (0);
-}
-
-
-void 
-LteCtrlSinrChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
-{
-  NS_LOG_FUNCTION (this << sinr << duration);
-  if (m_sumSinr == 0)
-    {
-      m_sumSinr = Create<SpectrumValue> (sinr.GetSpectrumModel ());
-    }
-  (*m_sumSinr) += sinr * duration.GetSeconds ();
-  m_totDuration += duration;
-}
- 
-void 
-LteCtrlSinrChunkProcessor::End ()
-{
-  NS_LOG_FUNCTION (this);
-  if (m_totDuration.GetSeconds () > 0)
-    {
-      m_phy->GenerateCtrlCqiReport ((*m_sumSinr) / m_totDuration.GetSeconds ());
-      if (m_spectrumPhy)
-        {
-          m_spectrumPhy->UpdateSinrPerceived ((*m_sumSinr) / m_totDuration.GetSeconds ());
-        }
-    }
-  else
-    {
-      NS_LOG_WARN ("m_numSinr == 0");
-    }
-}
-
-
-// ------------- LteDataSinrChunkProcessor ------------------------------
-
-LteDataSinrChunkProcessor::LteDataSinrChunkProcessor (Ptr<LteSpectrumPhy> s, Ptr<LtePhy> p)
-: m_spectrumPhy (s),
-  m_phy (p)
-{
-  NS_LOG_FUNCTION (this << p);
-  NS_ASSERT (m_spectrumPhy);
-  NS_ASSERT (m_phy);
-}
-
-LteDataSinrChunkProcessor::LteDataSinrChunkProcessor (Ptr<LteSpectrumPhy> p)
-: m_spectrumPhy (p),
-  m_phy (0)
-{
-  NS_LOG_FUNCTION (this << p);
-  NS_ASSERT (m_spectrumPhy);
-  
-}
-
-
-
-LteDataSinrChunkProcessor::~LteDataSinrChunkProcessor ()
-{
-  NS_LOG_FUNCTION (this);
-}
-
-
-void 
-LteDataSinrChunkProcessor::Start ()
-{
-  NS_LOG_FUNCTION (this);
-  m_sumSinr = 0;
-  m_totDuration = MicroSeconds (0);
-}
-
-
-void 
-LteDataSinrChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
-{
-  NS_LOG_FUNCTION (this << sinr << duration);
-  if (m_sumSinr == 0)
-  {
-    m_sumSinr = Create<SpectrumValue> (sinr.GetSpectrumModel ());
-  }
-  (*m_sumSinr) += sinr * duration.GetSeconds ();
-  m_totDuration += duration;
-}
-
-void 
-LteDataSinrChunkProcessor::End ()
-{
-  NS_LOG_FUNCTION (this);
-  if (m_totDuration.GetSeconds () > 0)
-  {
-    m_spectrumPhy->UpdateSinrPerceived ((*m_sumSinr) / m_totDuration.GetSeconds ());
-    if (m_phy)
-      {
-        m_phy->GenerateDataCqiReport ((*m_sumSinr) / m_totDuration.GetSeconds ());
-      }
-  }
-  else
-  {
-    NS_LOG_WARN ("m_numSinr == 0");
-  }
-}
-
-
-
-
-// ------------- LteRsReceivedPowerChunkProcessor ------------------------------
-
-LteRsReceivedPowerChunkProcessor::LteRsReceivedPowerChunkProcessor (Ptr<LtePhy> p)
-: m_phy (p)
-{
-  NS_LOG_FUNCTION (this << p);
-  NS_ASSERT (m_phy);
-}
-
-LteRsReceivedPowerChunkProcessor::~LteRsReceivedPowerChunkProcessor ()
-{
-  NS_LOG_FUNCTION (this);
-}
-
-
-void
-LteRsReceivedPowerChunkProcessor::Start ()
-{
-  NS_LOG_FUNCTION (this);
-  m_sumSinr = 0;
-  m_totDuration = MicroSeconds (0);
-}
-
-
-void
-LteRsReceivedPowerChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
-{
-  NS_LOG_FUNCTION (this << sinr << duration);
-  if (m_sumSinr == 0)
-    {
-      m_sumSinr = Create<SpectrumValue> (sinr.GetSpectrumModel ());
-    }
-  (*m_sumSinr) += sinr * duration.GetSeconds ();
-  m_totDuration += duration;
-}
-
-void
-LteRsReceivedPowerChunkProcessor::End ()
-{
-  NS_LOG_FUNCTION (this);
-  if (m_totDuration.GetSeconds () > 0)
-    {
-      m_phy->ReportRsReceivedPower ((*m_sumSinr) / m_totDuration.GetSeconds ());
-    }
-  else
-    {
-      NS_LOG_WARN ("m_numSinr == 0");
-    }
-}
-
-
-
-
-
-// ------------- LteInterferencePowerChunkProcessor ------------------------------
-
-LteInterferencePowerChunkProcessor::LteInterferencePowerChunkProcessor (Ptr<LtePhy> p)
-: m_phy (p)
-{
-  NS_LOG_FUNCTION (this << p);
-  NS_ASSERT (m_phy);
-}
-
-LteInterferencePowerChunkProcessor::~LteInterferencePowerChunkProcessor ()
-{
-  NS_LOG_FUNCTION (this);
-}
-
-
-void
-LteInterferencePowerChunkProcessor::Start ()
-{
-  NS_LOG_FUNCTION (this);
-  m_sumSinr = 0;
-  m_totDuration = MicroSeconds (0);
-}
-
-
-void
-LteInterferencePowerChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
-{
-  NS_LOG_FUNCTION (this << sinr << duration);
-  if (m_sumSinr == 0)
-    {
-      m_sumSinr = Create<SpectrumValue> (sinr.GetSpectrumModel ());
-    }
-  (*m_sumSinr) += sinr * duration.GetSeconds ();
-  m_totDuration += duration;
-}
-
-void
-LteInterferencePowerChunkProcessor::End ()
-{
-  NS_LOG_FUNCTION (this);
-  if (m_totDuration.GetSeconds () > 0)
-    {
-      m_phy->ReportInterference ((*m_sumSinr) / m_totDuration.GetSeconds ());
-    }
-  else
-    {
-      NS_LOG_WARN ("m_numSinr == 0");
-    }
-}
-
-
-} // namespace ns3
--- a/src/lte/model/lte-sinr-chunk-processor.h	Thu Sep 04 23:13:41 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2009, 2010 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Nicola Baldo <nbaldo@cttc.es>
- * Modified by : Marco Miozzo <mmiozzo@cttc.es>
- *        (move from CQI to Ctrl and Data SINR Chunk processors)
- */
-
-
-#ifndef LTE_SINR_CHUNK_PROCESSOR_H
-#define LTE_SINR_CHUNK_PROCESSOR_H
-
-#include <ns3/spectrum-value.h>
-#include <ns3/ptr.h>
-#include <ns3/packet.h>
-#include <ns3/nstime.h>
-#include <ns3/object.h>
-#include <ns3/lte-phy.h>
-#include <ns3/lte-spectrum-phy.h>
-
-namespace ns3 {
-
-
-
-/** 
- * This abstract class is used to process the time-vs-frequency SINR chunk
- * of a received LTE signal which was calculated by the
- * LteInterference object.
- * 
- */
-class LteSinrChunkProcessor : public SimpleRefCount<LteSinrChunkProcessor> 
-{
-public:
-  virtual ~LteSinrChunkProcessor ();
-  virtual void Start () = 0;
-  virtual void EvaluateSinrChunk (const SpectrumValue& sinr, Time duration) = 0;
-  virtual void End () = 0;
-};
-
-
-
-
-/** 
- * The LteCtrlSinrChunkProcessor averages the calculated SINR over time 
- * for the Ctrl frame and therefore in charge of generating the CQI starting
- *  from the reference signals and the sinr values used for evaluating the 
- *  decodification error probability of the control channels (PCFICH + PDCCH)
- * 
- */
-class LteCtrlSinrChunkProcessor : public LteSinrChunkProcessor
-{
-public:
-  virtual ~LteCtrlSinrChunkProcessor ();
-  LteCtrlSinrChunkProcessor (Ptr<LtePhy> p);
-  LteCtrlSinrChunkProcessor (Ptr<LtePhy> p, Ptr<LteSpectrumPhy> s);
-  virtual void Start ();
-  virtual void EvaluateSinrChunk (const SpectrumValue& sinr, Time duration);
-  virtual void End ();
-private:
-  Ptr<SpectrumValue> m_sumSinr;
-  Time m_totDuration;
-  Ptr<LtePhy> m_phy;
-  Ptr<LteSpectrumPhy> m_spectrumPhy;
-};
-
-
-
-/** 
-* The LteDataSinrChunkProcessor averages the calculated SINR over time for
-* data frame and therefore in charge of generating the sinr values for
-*  evaluating the errors of data packets. Might be used also for generating 
-*  CQI based on data in case any LtePhy is attached.
-* 
-*/
-class LteDataSinrChunkProcessor : public LteSinrChunkProcessor
-{
-  public:
-    virtual ~LteDataSinrChunkProcessor ();
-    LteDataSinrChunkProcessor (Ptr<LteSpectrumPhy> p);
-    LteDataSinrChunkProcessor (Ptr<LteSpectrumPhy> s, Ptr<LtePhy> p);
-    virtual void Start ();
-    virtual void EvaluateSinrChunk (const SpectrumValue& sinr, Time duration);
-    virtual void End ();
-  private:
-    Ptr<SpectrumValue> m_sumSinr;
-    Time m_totDuration;
-    Ptr<LteSpectrumPhy> m_spectrumPhy;
-    Ptr<LtePhy> m_phy;
-};
-
-
-/**
-* The LteRsReceivedPowerChunkProcessor averages the received signal power
-* over time for data frame and therefore in charge of generating the
-*  power linear values for generating the RSRP tracing at eNB side
-*
-*/
-class LteRsReceivedPowerChunkProcessor : public LteSinrChunkProcessor
-{
-  public:
-    virtual ~LteRsReceivedPowerChunkProcessor ();
-    LteRsReceivedPowerChunkProcessor (Ptr<LtePhy> p);
-    virtual void Start ();
-    virtual void EvaluateSinrChunk (const SpectrumValue& sinr, Time duration);
-    virtual void End ();
-  private:
-    Ptr<SpectrumValue> m_sumSinr;
-    Time m_totDuration;
-    Ptr<LtePhy> m_phy;
-};
-
-
-
-
-/**
-* The LteInterferencePowerChunkProcessor averages the interference power 
-* over time for data frame and therefore in charge of generating the 
-* interference power linear values for generating the interference power
-* tracing at eNB side
-*
-*/
-class LteInterferencePowerChunkProcessor : public LteSinrChunkProcessor
-{
-  public:
-    virtual ~LteInterferencePowerChunkProcessor ();
-    LteInterferencePowerChunkProcessor (Ptr<LtePhy> p);
-    virtual void Start ();
-    virtual void EvaluateSinrChunk (const SpectrumValue& sinr, Time duration);
-    virtual void End ();
-  private:
-    Ptr<SpectrumValue> m_sumSinr;
-    Time m_totDuration;
-    Ptr<LtePhy> m_phy;
-};
-
-
-
-
-
-} // namespace ns3
-
-
-
-#endif /* LTE_SINR_PROCESSOR_H */
--- a/src/lte/model/lte-spectrum-phy.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-spectrum-phy.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -31,7 +31,7 @@
 #include "lte-spectrum-signal-parameters.h"
 #include "lte-net-device.h"
 #include "lte-radio-bearer-tag.h"
-#include "lte-sinr-chunk-processor.h"
+#include "lte-chunk-processor.h"
 #include "lte-phy-tag.h"
 #include <ns3/lte-mi-error-model.h>
 #include <ns3/lte-radio-bearer-tag.h>
@@ -1116,32 +1116,37 @@
 
 
 void
-LteSpectrumPhy::AddRsPowerChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteSpectrumPhy::AddRsPowerChunkProcessor (Ptr<LteChunkProcessor> p)
 {
   m_interferenceCtrl->AddRsPowerChunkProcessor (p);
 }
 
+void
+LteSpectrumPhy::AddDataPowerChunkProcessor (Ptr<LteChunkProcessor> p)
+{
+  m_interferenceData->AddRsPowerChunkProcessor (p);
+}
 
 void
-LteSpectrumPhy::AddDataSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteSpectrumPhy::AddDataSinrChunkProcessor (Ptr<LteChunkProcessor> p)
 {
   m_interferenceData->AddSinrChunkProcessor (p);
 }
 
 void
-LteSpectrumPhy::AddInterferenceCtrlChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteSpectrumPhy::AddInterferenceCtrlChunkProcessor (Ptr<LteChunkProcessor> p)
 {
   m_interferenceCtrl->AddInterferenceChunkProcessor (p);
 }
 
 void
-LteSpectrumPhy::AddInterferenceDataChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteSpectrumPhy::AddInterferenceDataChunkProcessor (Ptr<LteChunkProcessor> p)
 {
   m_interferenceData->AddInterferenceChunkProcessor (p);
 }
 
 void
-LteSpectrumPhy::AddCtrlSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteSpectrumPhy::AddCtrlSinrChunkProcessor (Ptr<LteChunkProcessor> p)
 {
   m_interferenceCtrl->AddSinrChunkProcessor (p);
 }
--- a/src/lte/model/lte-spectrum-phy.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-spectrum-phy.h	Fri Sep 05 01:12:55 2014 +0200
@@ -326,41 +326,49 @@
   /**
   *
   *
-  * \param p the new LteSinrChunkProcessor to be added to the RS power 
+  * \param p the new LteChunkProcessor to be added to the RS power
   *          processing chain
   */
-  void AddRsPowerChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+  void AddRsPowerChunkProcessor (Ptr<LteChunkProcessor> p);
   
+  /**
+  *
+  *
+  * \param p the new LteChunkProcessor to be added to the Data Channel power
+  *          processing chain
+  */
+  void AddDataPowerChunkProcessor (Ptr<LteChunkProcessor> p);
+
   /** 
   * 
   * 
-  * \param p the new LteSinrChunkProcessor to be added to the data processing chain
+  * \param p the new LteChunkProcessor to be added to the data processing chain
   */
-  void AddDataSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+  void AddDataSinrChunkProcessor (Ptr<LteChunkProcessor> p);
 
   /**
-  *  LteSinrChunkProcessor devoted to evaluate interference + noise power
+  *  LteChunkProcessor devoted to evaluate interference + noise power
   *  in control symbols of the subframe
   *
-  * \param p the new LteSinrChunkProcessor to be added to the data processing chain
+  * \param p the new LteChunkProcessor to be added to the data processing chain
   */
-  void AddInterferenceCtrlChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+  void AddInterferenceCtrlChunkProcessor (Ptr<LteChunkProcessor> p);
 
   /**
-  *  LteSinrChunkProcessor devoted to evaluate interference + noise power
+  *  LteChunkProcessor devoted to evaluate interference + noise power
   *  in data symbols of the subframe
   *
-  * \param p the new LteSinrChunkProcessor to be added to the data processing chain
+  * \param p the new LteChunkProcessor to be added to the data processing chain
   */
-  void AddInterferenceDataChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+  void AddInterferenceDataChunkProcessor (Ptr<LteChunkProcessor> p);
   
   
   /** 
   * 
   * 
-  * \param p the new LteSinrChunkProcessor to be added to the ctrl processing chain
+  * \param p the new LteChunkProcessor to be added to the ctrl processing chain
   */
-  void AddCtrlSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+  void AddCtrlSinrChunkProcessor (Ptr<LteChunkProcessor> p);
   
   /** 
   * 
--- a/src/lte/model/lte-spectrum-value-helper.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-spectrum-value-helper.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -36,7 +36,7 @@
   vector<int>::const_iterator it = v.begin ();
   while (it != v.end ())
     {
-      os << *it << " " ;
+      os << *it << " ";
       ++it;
     }
   os << endl;
@@ -52,7 +52,7 @@
 /**
  * Table 5.7.3-1 "E-UTRA channel numbers" from 3GPP TS 36.101
  * The table was converted to C syntax doing a cut & paste from TS 36.101 and running the following filter:
- * awk '{if ((NR % 7) == 1) printf("{"); printf ("%s",$0); if ((NR % 7) == 0) printf("},\n"); else printf(", ");}' | sed 's/ – /, /g' 
+ * awk '{if ((NR % 7) == 1) printf("{"); printf ("%s",$0); if ((NR % 7) == 0) printf("},\n"); else printf(", ");}' | sed 's/ – /, /g'
  */
 static const struct EutraChannelNumbers
 {
@@ -255,6 +255,45 @@
   return txPsd;
 }
 
+Ptr<SpectrumValue>
+LteSpectrumValueHelper::CreateTxPowerSpectralDensity (uint16_t earfcn, uint8_t txBandwidthConfiguration, double powerTx, std::map<int, double> powerTxMap, std::vector <int> activeRbs)
+{
+  NS_LOG_FUNCTION (earfcn << (uint16_t) txBandwidthConfiguration << activeRbs);
+
+  Ptr<SpectrumModel> model = GetSpectrumModel (earfcn, txBandwidthConfiguration);
+  Ptr<SpectrumValue> txPsd = Create <SpectrumValue> (model);
+
+  // powerTx is expressed in dBm. We must convert it into natural unit.
+  double powerTxW = std::pow (10., (powerTx - 30) / 10);
+  double basicPowerTxW = std::pow (10., (powerTx - 30) / 10);
+
+  double txPowerDensity = (powerTxW / (txBandwidthConfiguration * 180000));
+
+  for (std::vector <int>::iterator it = activeRbs.begin (); it != activeRbs.end (); it++)
+    {
+      int rbId = (*it);
+
+      std::map<int, double>::iterator powerIt = powerTxMap.find (rbId);
+
+      if (powerIt != powerTxMap.end ())
+        {
+          powerTxW = std::pow (10., (powerIt->second - 30) / 10);
+          txPowerDensity = (powerTxW / (txBandwidthConfiguration * 180000));
+        }
+      else
+        {
+          txPowerDensity = (basicPowerTxW / (txBandwidthConfiguration * 180000));
+        }
+
+      (*txPsd)[rbId] = txPowerDensity;
+    }
+
+  NS_LOG_LOGIC (*txPsd);
+
+  return txPsd;
+}
+
+
 
 Ptr<SpectrumValue>
 LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (uint16_t earfcn, uint8_t txBandwidthConfiguration, double noiseFigure)
--- a/src/lte/model/lte-spectrum-value-helper.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-spectrum-value-helper.h	Fri Sep 05 01:12:55 2014 +0200
@@ -112,6 +112,27 @@
                                                           double powerTx,
                                                           std::vector <int> activeRbs);
 
+  /**
+   * create a spectrum value representing the power spectral
+   * density of a signal to be transmitted. See 3GPP TS 36.101 for
+   * a definition of most of the parameters described here.
+   *
+   * \param earfcn the carrier frequency (EARFCN) of the transmission
+   * \param bandwidth the Transmission Bandwidth Configuration in
+   * number of resource blocks
+   * \param powerTx the total power in dBm over the whole bandwidth
+   * \param powerTxMap the map of power in dBm for each RB,
+   * if map contain power for RB, powerTx is not used for this RB,
+   * otherwise powerTx is set for this RB
+   * \param activeRbs the list of Active Resource Blocks (PRBs)
+   *
+   * \return a pointer to a newly allocated SpectrumValue representing the TX Power Spectral Density in W/Hz for each Resource Block
+   */
+  static Ptr<SpectrumValue> CreateTxPowerSpectralDensity (uint16_t earfcn,
+                                                          uint8_t bandwidth,
+                                                          double powerTx,
+                                                          std::map<int, double> powerTxMap,
+                                                          std::vector <int> activeRbs);
 
   /**
    * create a SpectrumValue that models the power spectral density of AWGN
--- a/src/lte/model/lte-ue-cphy-sap.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-ue-cphy-sap.h	Fri Sep 05 01:12:55 2014 +0200
@@ -116,6 +116,13 @@
    */
   virtual void ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth) = 0;
 
+  /**
+   * \brief Configure referenceSignalPower
+   *
+   * \param referenceSignalPower received from eNB in SIB2
+   */
+  virtual void ConfigureReferenceSignalPower (int8_t referenceSignalPower) = 0;
+
   /** 
    * 
    * \param rnti the cell-specific UE identifier
@@ -220,6 +227,7 @@
   virtual void SynchronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn);
   virtual void SetDlBandwidth (uint8_t dlBandwidth);
   virtual void ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth);
+  virtual void ConfigureReferenceSignalPower (int8_t referenceSignalPower);
   virtual void SetRnti (uint16_t rnti);
   virtual void SetTransmissionMode (uint8_t txMode);
   virtual void SetSrsConfigurationIndex (uint16_t srcCi);
@@ -284,6 +292,13 @@
 
 template <class C>
 void 
+MemberLteUeCphySapProvider<C>::ConfigureReferenceSignalPower (int8_t referenceSignalPower)
+{
+  m_owner->DoConfigureReferenceSignalPower (referenceSignalPower);
+}
+
+template <class C>
+void
 MemberLteUeCphySapProvider<C>::SetRnti (uint16_t rnti)
 {
   m_owner->DoSetRnti (rnti);
--- a/src/lte/model/lte-ue-phy.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-ue-phy.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -35,9 +35,11 @@
 #include "lte-amc.h"
 #include "lte-ue-mac.h"
 #include "ff-mac-common.h"
-#include "lte-sinr-chunk-processor.h"
+#include "lte-chunk-processor.h"
 #include <ns3/lte-common.h>
 #include <ns3/pointer.h>
+#include <ns3/boolean.h>
+#include <ns3/lte-ue-power-control.h>
 
 NS_LOG_COMPONENT_DEFINE ("LteUePhy");
 
@@ -137,12 +139,14 @@
     m_subframeNo (0),
     m_rsReceivedPowerUpdated (false),
     m_rsInterferencePowerUpdated (false),
+    m_dataInterferencePowerUpdated (false),
     m_pssReceived (false),
     m_ueMeasurementsFilterPeriod (MilliSeconds (200)),
     m_ueMeasurementsFilterLast (MilliSeconds (0)),
     m_rsrpSinrSampleCounter (0)
 {
   m_amc = CreateObject <LteAmc> ();
+  m_powerControl = CreateObject <LteUePowerControl> ();
   m_uePhySapProvider = new UeMemberLteUePhySapProvider (this);
   m_ueCphySapProvider = new MemberLteUeCphySapProvider<LteUePhy> (this);
   m_macChTtiDelay = UL_PUSCH_TTIS_DELAY;
@@ -270,6 +274,11 @@
     .AddTraceSource ("StateTransition",
                      "Trace fired upon every UE PHY state transition",
                      MakeTraceSourceAccessor (&LteUePhy::m_stateTransitionTrace))
+    .AddAttribute ("EnableUplinkPowerControl",
+                   "If true Uplink Power Control will be enabled",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&LteUePhy::m_enableUplinkPowerControl),
+                   MakeBooleanChecker ())
   ;
   return tid;
 }
@@ -329,6 +338,7 @@
 {
   NS_LOG_FUNCTION (this << pow);
   m_txPower = pow;
+  m_powerControl->SetTxPower (pow);
 }
 
 double
@@ -338,6 +348,12 @@
   return m_txPower;
 }
 
+Ptr<LteUePowerControl>
+LteUePhy::GetUplinkPowerControl () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_powerControl;
+}
 
 uint8_t
 LteUePhy::GetMacChDelay (void) const
@@ -423,6 +439,14 @@
 {
   NS_LOG_FUNCTION (this);
 
+  if (m_dataInterferencePowerUpdated)
+    {
+      SpectrumValue mixedSinr = m_rsReceivedPower / m_dataInterferencePower;
+      GenerateMixedCqiReport (mixedSinr);
+      m_dataInterferencePowerUpdated = false;
+      return;
+    }
+
   NS_ASSERT (m_state != CELL_SEARCH);
   NS_ASSERT (m_cellId > 0);
 
@@ -542,6 +566,123 @@
 }
 
 void
+LteUePhy::GenerateMixedCqiReport (const SpectrumValue& sinr)
+{
+  NS_LOG_FUNCTION (this);
+
+  NS_ASSERT (m_state != CELL_SEARCH);
+  NS_ASSERT (m_cellId > 0);
+
+  if (m_dlConfigured && m_ulConfigured && (m_rnti > 0))
+    {
+      // check periodic wideband CQI
+      if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity)
+        {
+          Ptr<LteUeNetDevice> thisDevice = GetDevice ()->GetObject<LteUeNetDevice> ();
+          Ptr<DlCqiLteControlMessage> msg = CreateDlCqiFeedbackMessage (sinr);
+          if (msg)
+            {
+              DoSendLteControlMessage (msg);
+            }
+          m_p10CqiLast = Simulator::Now ();
+        }
+      // check aperiodic high-layer configured subband CQI
+      if  (Simulator::Now () > m_a30CqiLast + m_a30CqiPeriocity)
+        {
+          Ptr<LteUeNetDevice> thisDevice = GetDevice ()->GetObject<LteUeNetDevice> ();
+          Ptr<DlCqiLteControlMessage> msg = CreateDlCqiFeedbackMessage (sinr);
+          if (msg)
+            {
+              DoSendLteControlMessage (msg);
+            }
+          m_a30CqiLast = Simulator::Now ();
+        }
+    }
+
+  // Generate PHY trace
+  m_rsrpSinrSampleCounter++;
+  if (m_rsrpSinrSampleCounter==m_rsrpSinrSamplePeriod)
+    {
+      NS_ASSERT_MSG (m_rsReceivedPowerUpdated, " RS received power info obsolete");
+      // RSRP evaluated as averaged received power among RBs
+      double sum = 0.0;
+      uint8_t rbNum = 0;
+      Values::const_iterator it;
+      for (it = m_rsReceivedPower.ConstValuesBegin (); it != m_rsReceivedPower.ConstValuesEnd (); it++)
+        {
+          // convert PSD [W/Hz] to linear power [W] for the single RE
+          // we consider only one RE for the RS since the channel is
+          // flat within the same RB
+          double powerTxW = ((*it) * 180000.0) / 12.0;
+          sum += powerTxW;
+          rbNum++;
+        }
+      double rsrp = (rbNum > 0) ? (sum / rbNum) : DBL_MAX;
+      // averaged SINR among RBs
+      sum = 0.0;
+      rbNum = 0;
+      for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++)
+        {
+          sum += (*it);
+          rbNum++;
+        }
+      double avSinr = (rbNum > 0) ? (sum / rbNum) : DBL_MAX;
+      NS_LOG_INFO (this << " cellId " << m_cellId << " rnti " << m_rnti << " RSRP " << rsrp << " SINR " << avSinr);
+
+      m_reportCurrentCellRsrpSinrTrace (m_cellId, m_rnti, rsrp, avSinr);
+      m_rsrpSinrSampleCounter = 0;
+    }
+
+  if (m_pssReceived)
+    {
+      // measure instantaneous RSRQ now
+      NS_ASSERT_MSG (m_rsInterferencePowerUpdated, " RS interference power info obsolete");
+
+      std::list <PssElement>::iterator itPss = m_pssList.begin ();
+      while (itPss != m_pssList.end ())
+        {
+          uint16_t rbNum = 0;
+          double rsrqSum = 0.0;
+
+          Values::const_iterator itIntN = m_rsInterferencePower.ConstValuesBegin ();
+          Values::const_iterator itPj = m_rsReceivedPower.ConstValuesBegin ();
+          for (itPj = m_rsReceivedPower.ConstValuesBegin ();
+               itPj != m_rsReceivedPower.ConstValuesEnd ();
+               itIntN++, itPj++)
+            {
+              rbNum++;
+              // convert PSD [W/Hz] to linear power [W] for the single RE
+              double noisePowerTxW = ((*itIntN) * 180000.0) / 12.0;
+              double intPowerTxW = ((*itPj) * 180000.0) / 12.0;
+              rsrqSum += (2 * (noisePowerTxW + intPowerTxW));
+            }
+
+          NS_ASSERT (rbNum == (*itPss).nRB);
+          double rsrq_dB = 10 * log10 ((*itPss).pssPsdSum / rsrqSum);
+
+          if (rsrq_dB > m_pssReceptionThreshold)
+            {
+              NS_LOG_INFO (this << " PSS RNTI " << m_rnti << " cellId " << m_cellId
+                                << " has RSRQ " << rsrq_dB << " and RBnum " << rbNum);
+              // store measurements
+              std::map <uint16_t, UeMeasurementsElement>::iterator itMeasMap;
+              itMeasMap = m_ueMeasurementsMap.find ((*itPss).cellId);
+              NS_ASSERT (itMeasMap != m_ueMeasurementsMap.end ());
+              (*itMeasMap).second.rsrqSum += rsrq_dB;
+              (*itMeasMap).second.rsrqNum++;
+            }
+
+          itPss++;
+
+        }         // end of while (itPss != m_pssList.end ())
+
+      m_pssList.clear ();
+
+    }     // end of if (m_pssReceived)
+
+}
+
+void
 LteUePhy::ReportInterference (const SpectrumValue& interf)
 {
   NS_LOG_FUNCTION (this << interf);
@@ -550,14 +691,38 @@
 }
 
 void
+LteUePhy::ReportDataInterference (const SpectrumValue& interf)
+{
+  NS_LOG_FUNCTION (this << interf);
+
+  m_dataInterferencePowerUpdated = true;
+  m_dataInterferencePower = interf;
+}
+
+void
 LteUePhy::ReportRsReceivedPower (const SpectrumValue& power)
 {
   NS_LOG_FUNCTION (this << power);
   m_rsReceivedPowerUpdated = true;
   m_rsReceivedPower = power;
-}
 
+  if (m_enableUplinkPowerControl)
+    {
+      double sum = 0;
+      uint32_t rbNum = 0;
+      Values::const_iterator it;
+      for (it = m_rsReceivedPower.ConstValuesBegin (); it != m_rsReceivedPower.ConstValuesEnd (); it++)
+        {
+          double powerTxW = ((*it) * 180000);
+          sum += powerTxW;
+          rbNum++;
+        }
+      double rsrp = 10 * log10 (sum) + 30;
 
+      NS_LOG_INFO ("RSRP: " << rsrp);
+      m_powerControl->SetRsrp (rsrp);
+    }
+}
 
 Ptr<DlCqiLteControlMessage>
 LteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr)
@@ -728,144 +893,149 @@
   NS_LOG_FUNCTION (this);
 
   std::list<Ptr<LteControlMessage> >::iterator it;
-  for (it = msgList.begin (); it != msgList.end(); it++)
-  {
-    Ptr<LteControlMessage> msg = (*it);
-  
-    if (msg->GetMessageType () == LteControlMessage::DL_DCI)
+  for (it = msgList.begin (); it != msgList.end (); it++)
     {
-      Ptr<DlDciLteControlMessage> msg2 = DynamicCast<DlDciLteControlMessage> (msg);
-      
-      DlDciListElement_s dci = msg2->GetDci ();
-      if (dci.m_rnti != m_rnti)
-        {
-          // DCI not for me
-          continue;
-        }
-      
-      if (dci.m_resAlloc != 0)
-      {
-        NS_FATAL_ERROR ("Resource Allocation type not implemented");
-      }
-      
-      std::vector <int> dlRb;
-      
-      // translate the DCI to Spectrum framework
-      uint32_t mask = 0x1;
-      for (int i = 0; i < 32; i++)
-      {
-        if (((dci.m_rbBitmap & mask) >> i) == 1)
+      Ptr<LteControlMessage> msg = (*it);
+
+      if (msg->GetMessageType () == LteControlMessage::DL_DCI)
         {
-          for (int k = 0; k < GetRbgSize (); k++)
-          {
-            dlRb.push_back ((i * GetRbgSize ()) + k);
+          Ptr<DlDciLteControlMessage> msg2 = DynamicCast<DlDciLteControlMessage> (msg);
+
+          DlDciListElement_s dci = msg2->GetDci ();
+          if (dci.m_rnti != m_rnti)
+            {
+              // DCI not for me
+              continue;
+            }
+
+          if (dci.m_resAlloc != 0)
+            {
+              NS_FATAL_ERROR ("Resource Allocation type not implemented");
+            }
+
+          std::vector <int> dlRb;
+
+          // translate the DCI to Spectrum framework
+          uint32_t mask = 0x1;
+          for (int i = 0; i < 32; i++)
+            {
+              if (((dci.m_rbBitmap & mask) >> i) == 1)
+                {
+                  for (int k = 0; k < GetRbgSize (); k++)
+                    {
+                      dlRb.push_back ((i * GetRbgSize ()) + k);
 //             NS_LOG_DEBUG(this << " RNTI " << m_rnti << " RBG " << i << " DL-DCI allocated PRB " << (i*GetRbgSize()) + k);
-          }
-        }
-        mask = (mask << 1);
-      }
-      
-      // send TB info to LteSpectrumPhy
-      NS_LOG_DEBUG (this << " UE " << m_rnti << " DL-DCI " << dci.m_rnti << " bitmap "  << dci.m_rbBitmap);
-      for (uint8_t i = 0; i < dci.m_tbsSize.size (); i++)
-      {
-        m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_ndi.at (i), dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i, dci.m_harqProcess, dci.m_rv.at (i), true /* DL */);
-      }
-      
-      SetSubChannelsForReception (dlRb);
-      
-      
-    }
-    else if (msg->GetMessageType () == LteControlMessage::UL_DCI) 
-    {
-      // set the uplink bandwidth according to the UL-CQI
-      Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
-      UlDciListElement_s dci = msg2->GetDci ();
-      if (dci.m_rnti != m_rnti)
-        {
-          // DCI not for me
-          continue;
+                    }
+                }
+              mask = (mask << 1);
+            }
+          if (m_enableUplinkPowerControl)
+            {
+              m_powerControl->ReportTpc (dci.m_tpc);
+            }
+
+
+          // send TB info to LteSpectrumPhy
+          NS_LOG_DEBUG (this << " UE " << m_rnti << " DL-DCI " << dci.m_rnti << " bitmap "  << dci.m_rbBitmap);
+          for (uint8_t i = 0; i < dci.m_tbsSize.size (); i++)
+            {
+              m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_ndi.at (i), dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i, dci.m_harqProcess, dci.m_rv.at (i), true /* DL */);
+            }
+
+          SetSubChannelsForReception (dlRb);
+
+
         }
-      NS_LOG_INFO (this << " UL DCI");
-      std::vector <int> ulRb;
-      for (int i = 0; i < dci.m_rbLen; i++)
-      {
-        ulRb.push_back (i + dci.m_rbStart);
-        //NS_LOG_DEBUG (this << " UE RB " << i + dci.m_rbStart);
-      }
-      QueueSubChannelsForTransmission (ulRb);
-      // fire trace of UL Tx PHY stats
-      HarqProcessInfoList_t harqInfoList = m_harqPhyModule->GetHarqProcessInfoUl (m_rnti, 0);
-      PhyTransmissionStatParameters params;
-      params.m_cellId = m_cellId;
-      params.m_imsi = 0; // it will be set by DlPhyTransmissionCallback in LteHelper
-      params.m_timestamp = Simulator::Now ().GetMilliSeconds () + UL_PUSCH_TTIS_DELAY;
-      params.m_rnti = m_rnti;
-      params.m_txMode = 0; // always SISO for UE
-      params.m_layer = 0;
-      params.m_mcs = dci.m_mcs;
-      params.m_size = dci.m_tbSize;
-      params.m_rv = harqInfoList.size ();
-      params.m_ndi = dci.m_ndi;
-      m_ulPhyTransmission (params);
-      // pass the info to the MAC
-      m_uePhySapUser->ReceiveLteControlMessage (msg);
+      else if (msg->GetMessageType () == LteControlMessage::UL_DCI)
+        {
+          // set the uplink bandwidth according to the UL-CQI
+          Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
+          UlDciListElement_s dci = msg2->GetDci ();
+          if (dci.m_rnti != m_rnti)
+            {
+              // DCI not for me
+              continue;
+            }
+          NS_LOG_INFO (this << " UL DCI");
+          std::vector <int> ulRb;
+          for (int i = 0; i < dci.m_rbLen; i++)
+            {
+              ulRb.push_back (i + dci.m_rbStart);
+              //NS_LOG_DEBUG (this << " UE RB " << i + dci.m_rbStart);
+            }
+          QueueSubChannelsForTransmission (ulRb);
+          // fire trace of UL Tx PHY stats
+          HarqProcessInfoList_t harqInfoList = m_harqPhyModule->GetHarqProcessInfoUl (m_rnti, 0);
+          PhyTransmissionStatParameters params;
+          params.m_cellId = m_cellId;
+          params.m_imsi = 0; // it will be set by DlPhyTransmissionCallback in LteHelper
+          params.m_timestamp = Simulator::Now ().GetMilliSeconds () + UL_PUSCH_TTIS_DELAY;
+          params.m_rnti = m_rnti;
+          params.m_txMode = 0; // always SISO for UE
+          params.m_layer = 0;
+          params.m_mcs = dci.m_mcs;
+          params.m_size = dci.m_tbSize;
+          params.m_rv = harqInfoList.size ();
+          params.m_ndi = dci.m_ndi;
+          m_ulPhyTransmission (params);
+          // pass the info to the MAC
+          m_uePhySapUser->ReceiveLteControlMessage (msg);
+        }
+      else if (msg->GetMessageType () == LteControlMessage::RAR)
+        {
+          Ptr<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
+          if (rarMsg->GetRaRnti () == m_raRnti)
+            {
+              for (std::list<RarLteControlMessage::Rar>::const_iterator it = rarMsg->RarListBegin (); it != rarMsg->RarListEnd (); ++it)
+                {
+                  if (it->rapId != m_raPreambleId)
+                    {
+                      // UL grant not for me
+                      continue;
+                    }
+                  else
+                    {
+                      NS_LOG_INFO ("received RAR RNTI " << m_raRnti);
+                      // set the uplink bandwidht according to the UL grant
+                      std::vector <int> ulRb;
+                      for (int i = 0; i < it->rarPayload.m_grant.m_rbLen; i++)
+                        {
+                          ulRb.push_back (i + it->rarPayload.m_grant.m_rbStart);
+                        }
+
+                      QueueSubChannelsForTransmission (ulRb);
+                      // pass the info to the MAC
+                      m_uePhySapUser->ReceiveLteControlMessage (msg);
+                      // reset RACH variables with out of range values
+                      m_raPreambleId = 255;
+                      m_raRnti = 11;
+                    }
+                }
+            }
+        }
+      else if (msg->GetMessageType () == LteControlMessage::MIB)
+        {
+          NS_LOG_INFO ("received MIB");
+          NS_ASSERT (m_cellId > 0);
+          Ptr<MibLteControlMessage> msg2 = DynamicCast<MibLteControlMessage> (msg);
+          m_ueCphySapUser->RecvMasterInformationBlock (m_cellId, msg2->GetMib ());
+        }
+      else if (msg->GetMessageType () == LteControlMessage::SIB1)
+        {
+          NS_LOG_INFO ("received SIB1");
+          NS_ASSERT (m_cellId > 0);
+          Ptr<Sib1LteControlMessage> msg2 = DynamicCast<Sib1LteControlMessage> (msg);
+          m_ueCphySapUser->RecvSystemInformationBlockType1 (m_cellId, msg2->GetSib1 ());
+        }
+      else
+        {
+          // pass the message to UE-MAC
+          m_uePhySapUser->ReceiveLteControlMessage (msg);
+        }
+
     }
-    else if (msg->GetMessageType () == LteControlMessage::RAR)
-      {
-        Ptr<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
-        if (rarMsg->GetRaRnti () == m_raRnti)
-          {
-            for (std::list<RarLteControlMessage::Rar>::const_iterator it = rarMsg->RarListBegin (); it != rarMsg->RarListEnd (); ++it)
-              {
-                if (it->rapId != m_raPreambleId)
-                  {
-                    // UL grant not for me
-                    continue;
-                  }
-                else
-                  {
-                    NS_LOG_INFO ("received RAR RNTI " << m_raRnti);
-                    // set the uplink bandwidht according to the UL grant
-                    std::vector <int> ulRb;
-                    for (int i = 0; i < it->rarPayload.m_grant.m_rbLen; i++)
-                    {
-                      ulRb.push_back (i + it->rarPayload.m_grant.m_rbStart);
-                    }
 
-                    QueueSubChannelsForTransmission (ulRb);
-                    // pass the info to the MAC
-                    m_uePhySapUser->ReceiveLteControlMessage (msg);
-                    // reset RACH variables with out of range values
-                    m_raPreambleId = 255;
-                    m_raRnti = 11;
-                  }
-              }
-          }
-      }
-    else if (msg->GetMessageType () == LteControlMessage::MIB) 
-      {
-        NS_LOG_INFO ("received MIB");
-        NS_ASSERT (m_cellId > 0);
-        Ptr<MibLteControlMessage> msg2 = DynamicCast<MibLteControlMessage> (msg);
-        m_ueCphySapUser->RecvMasterInformationBlock (m_cellId, msg2->GetMib ());
-      }
-    else if (msg->GetMessageType () == LteControlMessage::SIB1)
-      {
-        NS_LOG_INFO ("received SIB1");
-        NS_ASSERT (m_cellId > 0);
-        Ptr<Sib1LteControlMessage> msg2 = DynamicCast<Sib1LteControlMessage> (msg);
-        m_ueCphySapUser->RecvSystemInformationBlockType1 (m_cellId, msg2->GetSib1 ());
-      }
-    else
-    {
-      // pass the message to UE-MAC
-      m_uePhySapUser->ReceiveLteControlMessage (msg);
-    }
-    
-  }
-  
-  
+
 }
 
 
@@ -945,6 +1115,7 @@
   if (m_ulConfigured)
     {
       // update uplink transmission mask according to previous UL-CQIs
+      std::vector <int> rbMask = m_subChannelsForTransmissionQueue.at (0);
       SetSubChannelsForTransmission (m_subChannelsForTransmissionQueue.at (0));
 
       // shift the queue
@@ -953,7 +1124,7 @@
           m_subChannelsForTransmissionQueue.at (i-1) = m_subChannelsForTransmissionQueue.at (i);
         }
       m_subChannelsForTransmissionQueue.at (m_macChTtiDelay-1).clear ();
-  
+
       if (m_srsConfigured && (m_srsStartTime <= Simulator::Now ()))
         {
 
@@ -966,7 +1137,7 @@
                                                     this);
             }
         }
-      
+
       std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
       // send packets in queue
       NS_LOG_LOGIC (this << " UE - start slot for PUSCH + PUCCH - RNTI " << m_rnti << " CELLID " << m_cellId);
@@ -974,6 +1145,11 @@
       Ptr<PacketBurst> pb = GetPacketBurst ();
       if (pb)
         {
+          if (m_enableUplinkPowerControl)
+            {
+              m_txPower = m_powerControl->GetPuschTxPower (rbMask);
+              SetSubChannelsForTransmission (rbMask);
+            }
           m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
         }
       else
@@ -983,6 +1159,12 @@
             {
               NS_LOG_LOGIC (this << " UE - start TX PUCCH (NO PUSCH)");
               std::vector <int> dlRb;
+
+              if (m_enableUplinkPowerControl)
+                {
+                  m_txPower = m_powerControl->GetPucchTxPower (dlRb);
+                }
+
               SetSubChannelsForTransmission (dlRb);
               m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
             }
@@ -992,10 +1174,10 @@
             }
         }
     }  // m_configured
-  
+
   // trigger the MAC
   m_uePhySapUser->SubframeIndication (frameNo, subframeNo);
-  
+
   m_subframeNo = subframeNo;
   ++subframeNo;
   if (subframeNo > 10)
@@ -1003,7 +1185,7 @@
       ++frameNo;
       subframeNo = 1;
     }
-  
+
   // schedule next subframe indication
   Simulator::Schedule (Seconds (GetTti ()), &LteUePhy::SubframeIndication, this, frameNo, subframeNo);
 }
@@ -1020,6 +1202,12 @@
     {
       dlRb.push_back (i);
     }
+
+  if (m_enableUplinkPowerControl)
+    {
+      m_txPower = m_powerControl->GetSrsTxPower (dlRb);
+    }
+
   SetSubChannelsForTransmission (dlRb);
   m_uplinkSpectrumPhy->StartTxUlSrsFrame ();
 }
@@ -1140,12 +1328,21 @@
   m_ulConfigured = true;
 }
 
+void
+LteUePhy::DoConfigureReferenceSignalPower (int8_t referenceSignalPower)
+{
+  NS_LOG_FUNCTION (this);
+  m_powerControl->ConfigureReferenceSignalPower (referenceSignalPower);
+}
  
 void
 LteUePhy::DoSetRnti (uint16_t rnti)
 {
   NS_LOG_FUNCTION (this << rnti);
   m_rnti = rnti;
+
+  m_powerControl->SetCellId (m_cellId);
+  m_powerControl->SetRnti (m_rnti);
 }
  
 void
--- a/src/lte/model/lte-ue-phy.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-ue-phy.h	Fri Sep 05 01:12:55 2014 +0200
@@ -33,6 +33,7 @@
 #include <ns3/ptr.h>
 #include <ns3/lte-amc.h>
 #include <set>
+#include <ns3/lte-ue-power-control.h>
 
 
 namespace ns3 {
@@ -117,6 +118,12 @@
    * \return the transmission power in dBm
    */
   double GetTxPower () const;
+
+  /**
+   * \return ptr to UE Uplink Power Control entity
+   */
+  Ptr<LteUePowerControl> GetUplinkPowerControl () const;
+
   /**
    * \param nf the noise figure in dB
    */
@@ -183,7 +190,9 @@
   // inherited from LtePhy
   virtual void GenerateCtrlCqiReport (const SpectrumValue& sinr);
   virtual void GenerateDataCqiReport (const SpectrumValue& sinr);
+  virtual void GenerateMixedCqiReport (const SpectrumValue& sinr);
   virtual void ReportInterference (const SpectrumValue& interf);
+  virtual void ReportDataInterference (const SpectrumValue& interf);
   virtual void ReportRsReceivedPower (const SpectrumValue& power);
 
   // callbacks for LteSpectrumPhy
@@ -260,6 +269,7 @@
   void DoSynchronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn);
   void DoSetDlBandwidth (uint8_t ulBandwidth);
   void DoConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth);
+  void DoConfigureReferenceSignalPower (int8_t referenceSignalPower);
   void DoSetRnti (uint16_t rnti);
   void DoSetTransmissionMode (uint8_t txMode);
   void DoSetSrsConfigurationIndex (uint16_t srcCi);
@@ -277,6 +287,9 @@
 
   Ptr<LteAmc> m_amc;
 
+  bool m_enableUplinkPowerControl;
+  Ptr<LteUePowerControl> m_powerControl;
+
   Time m_p10CqiPeriocity; /**< Wideband Periodic CQI: 2, 5, 10, 16, 20, 32, 40, 64, 80 or 160 ms */
   Time m_p10CqiLast;
 
@@ -316,6 +329,9 @@
   bool m_rsInterferencePowerUpdated;
   SpectrumValue m_rsInterferencePower;
 
+  bool m_dataInterferencePowerUpdated;
+  SpectrumValue m_dataInterferencePower;
+
   bool m_pssReceived;
   struct PssElement
   {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ue-power-control.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,455 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-ue-power-control.h"
+#include <ns3/log.h>
+#include <ns3/boolean.h>
+#include <ns3/double.h>
+#include <ns3/integer.h>
+#include <ns3/math.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteUePowerControl");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteUePowerControl);
+
+LteUePowerControl::LteUePowerControl ()
+{
+  NS_LOG_FUNCTION (this);
+  m_deltaTF = 0;
+  m_fc = 0;
+  m_pathLoss = 100; //initial value
+  m_curPuschTxPower = 10;
+  m_curPucchTxPower = 10;
+  m_curSrsTxPower = 10;
+  m_txPower = 10;
+
+  m_cellId = 0;
+  m_rnti = 0;
+
+  m_M_Pusch = 0;
+  m_rsrpSet = false;
+}
+
+LteUePowerControl::~LteUePowerControl ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteUePowerControl::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteUePowerControl::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+TypeId
+LteUePowerControl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LteUePowerControl")
+    .SetParent<Object> ()
+    .AddConstructor<LteUePowerControl> ()
+    .AddAttribute ("ClosedLoop",
+                   "If true Closed Loop mode will be active, otherwise Open Loop",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&LteUePowerControl::m_closedLoop),
+                   MakeBooleanChecker ())
+    .AddAttribute ("AccumulationEnabled",
+                   "If true TCP accumulation mode will be active, otherwise absolute mode will be active",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&LteUePowerControl::m_accumulationEnabled),
+                   MakeBooleanChecker ())
+    .AddAttribute ("Alpha",
+                   "Value of Alpha paramter",
+                   DoubleValue (1.0),
+                   MakeDoubleAccessor (&LteUePowerControl::SetAlpha),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("Pcmax",
+                   "Max Transmission power in dBm, Default value 23 dBm"
+                   "TS36.101 section 6.2.3",
+                   DoubleValue (23.0),
+                   MakeDoubleAccessor (&LteUePowerControl::m_Pcmax),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("Pcmin",
+                   "Min Transmission power in dBm, Default value -40 dBm"
+                   "TS36.101 section 6.2.3",
+                   DoubleValue (-40),
+                   MakeDoubleAccessor (&LteUePowerControl::m_Pcmin),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("PoNominalPusch",
+                   "P_O_NOMINAL_PUSCH   INT (-126 ... 24), Default value -80",
+                   IntegerValue (-80),
+                   MakeIntegerAccessor (&LteUePowerControl::SetPoNominalPusch),
+                   MakeIntegerChecker<int16_t> ())
+    .AddAttribute ("PoUePusch",
+                   "P_O_UE_PUSCH   INT(-8...7), Default value 0",
+                   IntegerValue (0),
+                   MakeIntegerAccessor (&LteUePowerControl::SetPoUePusch),
+                   MakeIntegerChecker<int16_t> ())
+    .AddAttribute ("PsrsOffset",
+                   "P_SRS_OFFSET   INT(0...15), Default value 7",
+                   IntegerValue (7),
+                   MakeIntegerAccessor (&LteUePowerControl::m_PsrsOffset),
+                   MakeIntegerChecker<int16_t> ())
+    .AddTraceSource ("ReportPuschTxPower",
+                     "Report PUSCH TxPower in dBm",
+                     MakeTraceSourceAccessor (&LteUePowerControl::m_reportPuschTxPower))
+    .AddTraceSource ("ReportPucchTxPower",
+                     "Report PUCCH TxPower in dBm",
+                     MakeTraceSourceAccessor (&LteUePowerControl::m_reportPucchTxPower))
+    .AddTraceSource ("ReportSrsTxPower",
+                     "Report SRS TxPower in dBm",
+                     MakeTraceSourceAccessor (&LteUePowerControl::m_reportSrsTxPower))
+  ;
+  return tid;
+}
+
+void
+LteUePowerControl::SetPcmax (double value)
+{
+  NS_LOG_FUNCTION (this);
+  m_Pcmax = value;
+}
+
+double
+LteUePowerControl::GetPcmax ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_Pcmax;
+}
+
+void
+LteUePowerControl::SetTxPower (double value)
+{
+  NS_LOG_FUNCTION (this);
+  m_txPower = value;
+  m_curPuschTxPower = value;
+  m_curPucchTxPower = value;
+  m_curSrsTxPower = value;
+}
+
+void
+LteUePowerControl::ConfigureReferenceSignalPower (int8_t referenceSignalPower)
+{
+  NS_LOG_FUNCTION (this);
+  m_referenceSignalPower = referenceSignalPower;
+}
+
+void
+LteUePowerControl::SetCellId (uint16_t cellId)
+{
+  NS_LOG_FUNCTION (this);
+  m_cellId = cellId;
+}
+void
+LteUePowerControl::SetRnti (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  m_rnti = rnti;
+}
+
+void
+LteUePowerControl::SetPoNominalPusch (int16_t value)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_PoNominalPusch.empty ())
+    {
+      m_PoNominalPusch.push_back (value);
+      m_PoNominalPusch.push_back (value);
+      m_PoNominalPusch.push_back (value);
+    }
+  else
+    {
+      m_PoNominalPusch[0] = value;
+      m_PoNominalPusch[1] = value;
+      m_PoNominalPusch[2] = value;
+    }
+
+}
+void
+LteUePowerControl::SetPoUePusch (int16_t value)
+{
+  NS_LOG_FUNCTION (this);
+  if (m_PoUePusch.empty ())
+    {
+      m_PoUePusch.push_back (value);
+      m_PoUePusch.push_back (value);
+      m_PoUePusch.push_back (0);
+    }
+  else
+    {
+      m_PoUePusch[0] = value;
+      m_PoUePusch[1] = value;
+      m_PoUePusch[2] = 0;
+    }
+}
+void
+LteUePowerControl::SetAlpha (double value)
+{
+  NS_LOG_FUNCTION (this);
+
+  uint32_t temp = value * 10;
+  switch (temp)
+    {
+    case 0:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+      break;
+    default:
+      NS_FATAL_ERROR ("Unexpected Alpha value");
+    }
+
+  if (m_alpha.empty ())
+    {
+      m_alpha.push_back (value);
+      m_alpha.push_back (value);
+      m_alpha.push_back (0);
+    }
+  else
+    {
+      m_alpha[0] = value;
+      m_alpha[1] = value;
+      m_alpha[2] = 1;
+    }
+
+}
+
+void
+LteUePowerControl::SetRsrp (double value)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_rsrpSet)
+    {
+      m_rsrp = value;
+      m_rsrpSet = true;
+      return;
+    }
+
+  double coeff = 0.7;
+  m_rsrp = coeff * m_rsrp + (1 - coeff) * value;
+  m_pathLoss = m_referenceSignalPower - m_rsrp;
+}
+
+void
+LteUePowerControl::ReportTpc (uint8_t tpc)
+{
+  NS_LOG_FUNCTION (this);
+
+  int delta = 0;
+  if (m_accumulationEnabled)
+    {
+      switch (tpc)
+        {
+        case 0:
+          delta = -1;
+          break;
+        case 1:
+          delta = 0;
+          break;
+        case 2:
+          delta = 1;
+          break;
+        case 3:
+          delta = 3;
+          break;
+        default:
+          NS_FATAL_ERROR ("Unexpected TPC value");
+        }
+    }
+  else
+    {
+      switch (tpc)
+        {
+        case 0:
+          delta = -4;
+          break;
+        case 1:
+          delta = -1;
+          break;
+        case 2:
+          delta = 1;
+          break;
+        case 3:
+          delta = 4;
+          break;
+        default:
+          NS_FATAL_ERROR ("Unexpected TPC value");
+        }
+    }
+
+  m_deltaPusch.push_back (delta);
+
+  if (m_closedLoop)
+    {
+      if (m_accumulationEnabled)
+        {
+          if (m_deltaPusch.size () == 4)
+            {
+              if ((m_curPuschTxPower <= m_Pcmin && m_deltaPusch.at (0) < 0)
+                  || (m_curPuschTxPower >= m_Pcmax && m_deltaPusch.at (0) > 0))
+                {
+                  //TPC commands for serving cell shall not be accumulated
+                  m_deltaPusch.erase (m_deltaPusch.begin ());
+                }
+              else
+                {
+                  m_fc = m_fc + m_deltaPusch.at (0);
+                  m_deltaPusch.erase (m_deltaPusch.begin ());
+                }
+            }
+          else
+            {
+              m_fc = 0;
+            }
+        }
+      else
+        {
+          m_fc = m_deltaPusch.at (0);
+          m_deltaPusch.erase (m_deltaPusch.begin ());
+        }
+    }
+  else
+    {
+      m_fc = 0;
+    }
+
+  NS_LOG_INFO ("ReportTpc: " << (int)tpc << " delta: " << delta << " Fc: " << m_fc);
+}
+
+void
+LteUePowerControl::SetSubChannelMask (std::vector <int> mask)
+{
+  NS_LOG_FUNCTION (this);
+  m_M_Pusch = mask.size ();
+}
+
+void
+LteUePowerControl::CalculatePuschTxPower ()
+{
+  NS_LOG_FUNCTION (this);
+  int32_t j = 1;
+  int32_t PoPusch = m_PoNominalPusch[j] + m_PoUePusch[j];
+
+  NS_LOG_INFO ("RB: " << m_M_Pusch << " m_PoPusch: " << PoPusch
+                      << " Alpha: " << m_alpha[j] << " PathLoss: " << m_pathLoss
+                      << " deltaTF: " << m_deltaTF << " fc: " << m_fc);
+
+  if ( m_M_Pusch > 0 )
+    {
+      m_curPuschTxPower = 10 * log10 (1.0 * m_M_Pusch) + PoPusch + m_alpha[j] * m_pathLoss + m_deltaTF + m_fc;
+      m_M_Pusch = 0;
+    }
+  else
+    {
+      m_curPuschTxPower = PoPusch + m_alpha[j] * m_pathLoss + m_fc;
+    }
+
+  NS_LOG_INFO ("CalcPower: " << m_curPuschTxPower << " MinPower: " << m_Pcmin << " MaxPower:" << m_Pcmax);
+
+  m_curPuschTxPower = m_curPuschTxPower > m_Pcmin ? m_curPuschTxPower : m_Pcmin;
+  m_curPuschTxPower = m_Pcmax < m_curPuschTxPower ? m_Pcmax : m_curPuschTxPower;
+  NS_LOG_INFO ("PuschTxPower: " << m_curPuschTxPower);
+}
+
+void
+LteUePowerControl::CalculatePucchTxPower ()
+{
+  NS_LOG_FUNCTION (this);
+  m_curPucchTxPower = m_curPuschTxPower;
+  NS_LOG_INFO ("PucchTxPower: " << m_curPucchTxPower);
+}
+
+void
+LteUePowerControl::CalculateSrsTxPower ()
+{
+  NS_LOG_FUNCTION (this);
+  int32_t j = 1;
+  int32_t PoPusch = m_PoNominalPusch[j] + m_PoUePusch[j];
+
+  NS_LOG_INFO ("RB: " << m_M_Pusch << " m_PoPusch: " << PoPusch
+                      << " Alpha: " << m_alpha[j] << " PathLoss: " << m_pathLoss
+                      << " deltaTF: " << m_deltaTF << " fc: " << m_fc);
+
+
+  double pSrsOffsetValue = -10.5 + m_PsrsOffset * 1.5;
+
+  m_curSrsTxPower = pSrsOffsetValue + 10 * log10 (m_srsBandwidth) + PoPusch + m_alpha[j] * m_pathLoss + m_fc;
+
+  NS_LOG_INFO ("CalcPower: " << m_curSrsTxPower << " MinPower: " << m_Pcmin << " MaxPower:" << m_Pcmax);
+
+  m_curSrsTxPower = m_curSrsTxPower > m_Pcmin ? m_curSrsTxPower : m_Pcmin;
+  m_curSrsTxPower = m_Pcmax < m_curSrsTxPower ? m_Pcmax : m_curSrsTxPower;
+  NS_LOG_INFO ("SrsTxPower: " << m_curSrsTxPower);
+}
+
+
+double
+LteUePowerControl::GetPuschTxPower (std::vector <int> dlRb)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_M_Pusch = dlRb.size ();
+  CalculatePuschTxPower ();
+
+  m_reportPuschTxPower (m_cellId, m_rnti, m_curPuschTxPower);
+
+  return m_curPuschTxPower;
+}
+
+double
+LteUePowerControl::GetPucchTxPower (std::vector <int> dlRb)
+{
+  NS_LOG_FUNCTION (this);
+
+  CalculatePucchTxPower ();
+
+  m_reportPucchTxPower (m_cellId, m_rnti, m_curPucchTxPower);
+
+  return m_curPucchTxPower;
+}
+
+double
+LteUePowerControl::GetSrsTxPower (std::vector <int> dlRb)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_srsBandwidth = dlRb.size ();
+  CalculateSrsTxPower ();
+
+  m_reportSrsTxPower (m_cellId, m_rnti, m_curSrsTxPower);
+
+  return m_curSrsTxPower;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-ue-power-control.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,138 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_UE_POWER_CONTROL_H
+#define LTE_UE_POWER_CONTROL_H
+
+#include <ns3/ptr.h>
+#include <ns3/traced-callback.h>
+#include <ns3/object.h>
+#include <vector>
+
+
+namespace ns3 {
+
+/**
+ * \brief This class realizes Uplink Power Control functionality
+ *
+ * When LteUePhy is about sending PUSCH/PUCCH/SRS it should ask
+ * LteUePowerControl for current channel TX power level and then
+ * use it while creating SpectrumValue for Uplink Transmission
+ *
+ * LteUePowerControl computes TX power level for PUSCH and SRS.
+ * PUCCH is realized in ideal way and PUSCH do not use any resources,
+ * so there is no need to compute power for that channel
+ *
+ * LteUePowerControlcomputes TX power based on some preconfigured
+ * parameters and current Path-loss. Path-loss is computed as difference
+ * between current RSRP and referenceSignalPower level. Current RSRP
+ * is passed to LteUePowerControl by LteUePhy. referenceSignalPower is
+ * configurable by attribute system
+ *
+ * Moreover, LteUePhy pass all received TPC values to LteUePowerControl,
+ * what is a part of Closed Loop Power Control functionality
+ */
+
+class LteUePowerControl : public Object
+{
+public:
+
+  LteUePowerControl ();
+  virtual ~LteUePowerControl ();
+
+  // inherited from Object
+  static TypeId GetTypeId (void);
+  virtual void DoInitialize (void);
+  virtual void DoDispose (void);
+
+  void SetPcmax (double value);
+  double GetPcmax ();
+
+  void SetTxPower (double value);
+  void ConfigureReferenceSignalPower (int8_t referenceSignalPower);
+
+  void SetCellId (uint16_t cellId);
+  void SetRnti (uint16_t rnti);
+
+  void SetPoNominalPusch (int16_t value);
+  void SetPoUePusch (int16_t value);
+  void SetAlpha (double value);
+
+  void SetRsrp (double value);
+  void ReportTpc (uint8_t tpc);
+
+  void CalculatePuschTxPower ();
+  void CalculatePucchTxPower ();
+  void CalculateSrsTxPower ();
+
+  double GetPuschTxPower (std::vector <int> rb);
+  double GetPucchTxPower (std::vector <int> rb);
+  double GetSrsTxPower (std::vector <int> rb);
+
+private:
+  void SetSubChannelMask (std::vector <int> mask);
+
+  double m_txPower;
+  double m_Pcmax;
+  double m_Pcmin;
+
+  double m_curPuschTxPower;
+  double m_curPucchTxPower;
+  double m_curSrsTxPower;
+
+  double m_referenceSignalPower;
+  bool m_rsrpSet;
+  double m_rsrp;
+
+  std::vector<int16_t> m_PoNominalPusch;
+  std::vector<int16_t> m_PoUePusch;
+
+  int16_t m_PsrsOffset;
+
+  uint16_t m_M_Pusch;
+  std::vector<double> m_alpha;
+  double m_pathLoss;
+  double m_deltaTF;
+
+  std::vector<int8_t> m_deltaPusch;
+  double m_fc;
+
+  uint16_t m_srsBandwidth;
+
+  bool m_closedLoop;
+  bool m_accumulationEnabled;
+
+  uint16_t m_cellId;
+  uint16_t m_rnti;
+  /**
+   * Trace information regarding Uplink TxPower
+   * uint16_t cellId, uint16_t rnti, double txPower
+   */
+  TracedCallback<uint16_t, uint16_t, double> m_reportPuschTxPower;
+  TracedCallback<uint16_t, uint16_t, double> m_reportPucchTxPower;
+  TracedCallback<uint16_t, uint16_t, double> m_reportSrsTxPower;
+
+};
+
+
+}
+
+#endif /* LTE_UE_POWER_CONTROL_H */
--- a/src/lte/model/lte-ue-rrc.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-ue-rrc.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -808,6 +808,7 @@
           rc.raResponseWindowSize = msg.sib2.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.raResponseWindowSize;
           m_cmacSapProvider->ConfigureRach (rc);
           m_cphySapProvider->ConfigureUplink (m_ulEarfcn, m_ulBandwidth);
+          m_cphySapProvider->ConfigureReferenceSignalPower(msg.sib2.radioResourceConfigCommon.pdschConfigCommon.referenceSignalPower);
           if (m_state == IDLE_WAIT_SIB2)
             {
               NS_ASSERT (m_connectionPending);
@@ -1102,7 +1103,7 @@
 {
   NS_LOG_FUNCTION (this);
   const struct LteRrcSap::PhysicalConfigDedicated& pcd = rrcd.physicalConfigDedicated;
-  
+
   if (pcd.haveAntennaInfoDedicated)
     {
       m_cphySapProvider->SetTransmissionMode (pcd.antennaInfo.transmissionMode);
@@ -1112,6 +1113,12 @@
       m_cphySapProvider->SetSrsConfigurationIndex (pcd.soundingRsUlConfigDedicated.srsConfigIndex);
     }
 
+  if (pcd.havePdschConfigDedicated)
+    {
+      // update PdschConfigDedicated (i.e. P_A value)
+	  m_pdschConfigDedicated = pcd.pdschConfigDedicated;
+   }
+
   std::list<LteRrcSap::SrbToAddMod>::const_iterator stamIt = rrcd.srbToAddModList.begin ();
   if (stamIt != rrcd.srbToAddModList.end ())
     {
--- a/src/lte/model/lte-ue-rrc.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/lte-ue-rrc.h	Fri Sep 05 01:12:55 2014 +0200
@@ -501,6 +501,8 @@
 
   uint8_t m_lastRrcTransactionIdentifier;
 
+  LteRrcSap::PdschConfigDedicated m_pdschConfigDedicated;
+
   uint8_t m_dlBandwidth; /**< downlink bandwidth in RBs */
   uint8_t m_ulBandwidth; /**< uplink bandwidth in RBs */
 
--- a/src/lte/model/pf-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/pf-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -30,6 +30,7 @@
 #include <cfloat>
 #include <set>
 
+
 NS_LOG_COMPONENT_DEFINE ("PfFfMacScheduler");
 
 namespace ns3 {
@@ -221,6 +222,8 @@
   m_amc = CreateObject <LteAmc> ();
   m_cschedSapProvider = new PfSchedulerMemberCschedSapProvider (this);
   m_schedSapProvider = new PfSchedulerMemberSchedSapProvider (this);
+  m_ffrSapProvider = 0;
+  m_ffrSapUser = new MemberLteFfrSapUser<PfFfMacScheduler> (this);
 }
 
 PfFfMacScheduler::~PfFfMacScheduler ()
@@ -241,6 +244,7 @@
   m_ulHarqProcessesDciBuffer.clear ();
   delete m_cschedSapProvider;
   delete m_schedSapProvider;
+  delete m_ffrSapUser;
 }
 
 TypeId
@@ -295,6 +299,18 @@
 }
 
 void
+PfFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+PfFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 PfFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -405,7 +421,7 @@
 PfFfMacScheduler::DoCschedUeReleaseReq (const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
-  
+
   m_uesTxMode.erase (params.m_rnti);
   m_dlHarqCurrentProcessId.erase (params.m_rnti);
   m_dlHarqProcessesStatus.erase  (params.m_rnti);
@@ -600,14 +616,14 @@
   NS_LOG_FUNCTION (this);
 
   std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
-  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers ++)
+  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers++)
     {
       for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
         {
           if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
             {
               // reset HARQ process
-              
+
               NS_LOG_DEBUG (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
               std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
               if (itStat == m_dlHarqProcessesStatus.end ())
@@ -623,7 +639,7 @@
             }
         }
     }
-  
+
 }
 
 
@@ -647,6 +663,16 @@
   uint16_t rbgAllocatedNum = 0;
   std::set <uint16_t> rntiAllocated;
   rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
+
+  rbgMap = m_ffrSapProvider->GetAvailableDlRbg ();
+  for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbgAllocatedNum++;
+        }
+    }
+
   FfMacSchedSapUser::SchedDlConfigIndParameters ret;
 
   //   update UL HARQ proc id
@@ -658,8 +684,48 @@
 
 
   // RACH Allocation
+  uint16_t rbAllocatedNum = 0;
+  std::vector <bool> ulRbMap;
+  ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+  ulRbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+  uint8_t maxContinuousUlBandwidth = 0;
+  uint8_t tmpMinBandwidth = 0;
+  uint16_t ffrRbStartOffset = 0;
+  uint16_t tmpFfrRbStartOffset = 0;
+  uint16_t index = 0;
+
+  for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+          if (tmpMinBandwidth > maxContinuousUlBandwidth)
+            {
+              maxContinuousUlBandwidth = tmpMinBandwidth;
+              ffrRbStartOffset = tmpFfrRbStartOffset;
+            }
+          tmpMinBandwidth = 0;
+        }
+      else
+        {
+          if (tmpMinBandwidth == 0)
+            {
+              tmpFfrRbStartOffset = index;
+            }
+          tmpMinBandwidth++;
+        }
+      index++;
+    }
+
+  if (tmpMinBandwidth > maxContinuousUlBandwidth)
+    {
+      maxContinuousUlBandwidth = tmpMinBandwidth;
+      ffrRbStartOffset = tmpFfrRbStartOffset;
+    }
+
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
   uint16_t rbStart = 0;
+  rbStart = ffrRbStartOffset;
   std::vector <struct RachListElement_s>::iterator itRach;
   for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
     {
@@ -674,7 +740,7 @@
       uint16_t rbLen = 1;
       uint16_t tbSizeBits = 0;
       // find lowest TB size that fits UL grant estimated size
-      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
+      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
         {
           rbLen++;
           tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
@@ -881,7 +947,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -899,7 +965,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1019,18 +1085,21 @@
           double rcqiMax = 0.0;
           for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
             {
+              if ((m_ffrSapProvider->IsDlRbgAvailableForUe (i, (*it).first)) == false)
+                continue;
+
               std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
               if ((itRnti != rntiAllocated.end ())||(!HarqProcessAvailability ((*it).first)))
                 {
                   // UE already allocated for HARQ or without HARQ process available -> drop it
                   if (itRnti != rntiAllocated.end ())
-                  {
-                    NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(*it).first);
-                  }
+                    {
+                      NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(*it).first);
+                    }
                   if (!HarqProcessAvailability ((*it).first))
-                  {
-                    NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*it).first);
-                  }
+                    {
+                      NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*it).first);
+                    }
                   continue;
                 }
               std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
@@ -1263,6 +1332,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
@@ -1330,7 +1401,7 @@
   NS_LOG_FUNCTION (this);
 
   m_rachList = params.m_rachList;
-  
+
   return;
 }
 
@@ -1338,6 +1409,7 @@
 PfFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
+  m_ffrSapProvider->ReportDlCqiInfo (params);
 
   for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
     {
@@ -1432,6 +1504,7 @@
   NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
 
   RefreshUlCqiMaps ();
+  m_ffrSapProvider->ReportUlCqiInfo (m_ueCqi);
 
   // Generate RBs map
   FfMacSchedSapUser::SchedUlConfigIndParameters ret;
@@ -1446,6 +1519,19 @@
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
 
   rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+
+  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+        }
+    }
+
+  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
+  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
+
   // remove RACH allocation
   for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
     {
@@ -1462,7 +1548,7 @@
       //   Process UL HARQ feedback
 
       for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
-        {        
+        {
           if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
             {
               // retx correspondent block: retrieve the UL-DCI
@@ -1525,7 +1611,7 @@
               ret.m_dciList.push_back (dci);
               rntiAllocated.insert (dci.m_rnti);
             }
-            else
+          else
             {
               NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
             }
@@ -1552,17 +1638,20 @@
           m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
           m_schedSapUser->SchedUlConfigInd (ret);
         }
-        
+
       return;  // no flows to be scheduled
     }
 
 
   // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
-  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
+
   if (rbPerFlow < 3)
     {
       rbPerFlow = 3;  // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
     }
+
   int rbAllocated = 0;
 
   std::map <uint16_t, pfsFlowPerf_t>::iterator itStats;
@@ -1608,15 +1697,16 @@
           if (rbPerFlow < 3)
             {
               // terminate allocation
-              rbPerFlow = 0;      
+              rbPerFlow = 0;
             }
         }
 
+      rbAllocated = 0;
       UlDciListElement_s uldci;
       uldci.m_rnti = (*it).first;
       uldci.m_rbLen = rbPerFlow;
       bool allocated = false;
-      NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
+
       while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
         {
           // check availability
@@ -1628,9 +1718,15 @@
                   free = false;
                   break;
                 }
+              if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
+                {
+                  free = false;
+                  break;
+                }
             }
           if (free)
             {
+              NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
               uldci.m_rbStart = rbAllocated;
 
               for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
@@ -1652,7 +1748,7 @@
               if (rbPerFlow < 3)
                 {
                   // terminate allocation
-                  rbPerFlow = 0;                 
+                  rbPerFlow = 0;
                 }
             }
         }
@@ -1660,12 +1756,13 @@
         {
           // unable to allocate new resource: finish scheduling
           m_nextRntiUl = (*it).first;
-          if (ret.m_dciList.size () > 0)
-            {
-              m_schedSapUser->SchedUlConfigInd (ret);
-            }
-          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
-          return;
+//          if (ret.m_dciList.size () > 0)
+//            {
+//              m_schedSapUser->SchedUlConfigInd (ret);
+//            }
+//          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
+//          return;
+          break;
         }
 
 
@@ -1700,8 +1797,8 @@
 
           // translate SINR -> cqi: WILD ACK: same as DL
           double s = log2 ( 1 + (
-                                 std::pow (10, minSinr / 10 )  /
-                                 ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
+                              std::pow (10, minSinr / 10 )  /
+                              ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
           cqi = m_amc->GetCqiFromSpectralEfficiency (s);
           if (cqi == 0)
             {
@@ -1848,7 +1945,7 @@
               uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
               buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
             }
-          
+
           uint16_t rnti = params.m_macCeList.at (i).m_rnti;
           NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
           it = m_ceBsrRxed.find (rnti);
@@ -1872,6 +1969,8 @@
 PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
+  m_ffrSapProvider->ReportUlCqiInfo (params);
+
 // retrieve the allocation for this subframe
   switch (m_ulCqiFilter)
     {
@@ -1956,7 +2055,7 @@
       break;
     case UlCqi_s::SRS:
       {
-        NS_LOG_DEBUG (this << " Collect SRS CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
+    	 NS_LOG_DEBUG (this << " Collect SRS CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
         // get the RNTI from vendor specific parameters
         uint16_t rnti = 0;
         NS_ASSERT (params.m_vendorSpecificList.size () > 0);
@@ -2113,7 +2212,7 @@
       // Update status queue
       if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
         {
-           (*it).second.m_rlcStatusPduSize = 0;
+          (*it).second.m_rlcStatusPduSize = 0;
         }
       else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
         {
@@ -2128,7 +2227,7 @@
               // overestimate RLC overhead rather than
               // underestimate it and risk unneeded
               // segmentation which increases delay 
-              rlcOverhead = 4;                                  
+              rlcOverhead = 4;
             }
           else
             {
@@ -2141,7 +2240,7 @@
               (*it).second.m_rlcTransmissionQueueSize = 0;
             }
           else
-            {                    
+            {
               (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
             }
         }
--- a/src/lte/model/pf-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/pf-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -29,7 +29,7 @@
 #include <map>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -93,6 +93,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class PfSchedulerMemberCschedSapProvider;
   friend class PfSchedulerMemberSchedSapProvider;
 
@@ -239,6 +243,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/pss-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/pss-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -225,6 +225,8 @@
   m_amc = CreateObject <LteAmc> ();
   m_cschedSapProvider = new PssSchedulerMemberCschedSapProvider (this);
   m_schedSapProvider = new PssSchedulerMemberSchedSapProvider (this);
+  m_ffrSapProvider = 0;
+  m_ffrSapUser = new MemberLteFfrSapUser<PssFfMacScheduler> (this);
 }
 
 PssFfMacScheduler::~PssFfMacScheduler ()
@@ -245,6 +247,7 @@
   m_ulHarqProcessesDciBuffer.clear ();
   delete m_cschedSapProvider;
   delete m_schedSapProvider;
+  delete m_ffrSapUser;
 }
 
 TypeId
@@ -309,6 +312,18 @@
 }
 
 void
+PssFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+PssFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 PssFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -676,6 +691,16 @@
   uint16_t rbgAllocatedNum = 0;
   std::set <uint16_t> rntiAllocated;
   rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
+
+  rbgMap = m_ffrSapProvider->GetAvailableDlRbg ();
+  for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbgAllocatedNum++;
+        }
+    }
+
   FfMacSchedSapUser::SchedDlConfigIndParameters ret;
 
   //   update UL HARQ proc id
@@ -686,8 +711,48 @@
     }
 
   // RACH Allocation
+  uint16_t rbAllocatedNum = 0;
+  std::vector <bool> ulRbMap;
+  ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+  ulRbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+  uint8_t maxContinuousUlBandwidth = 0;
+  uint8_t tmpMinBandwidth = 0;
+  uint16_t ffrRbStartOffset = 0;
+  uint16_t tmpFfrRbStartOffset = 0;
+  uint16_t index = 0;
+
+  for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+          if (tmpMinBandwidth > maxContinuousUlBandwidth)
+            {
+              maxContinuousUlBandwidth = tmpMinBandwidth;
+              ffrRbStartOffset = tmpFfrRbStartOffset;
+            }
+          tmpMinBandwidth = 0;
+        }
+      else
+        {
+          if (tmpMinBandwidth == 0)
+            {
+              tmpFfrRbStartOffset = index;
+            }
+          tmpMinBandwidth++;
+        }
+      index++;
+    }
+
+  if (tmpMinBandwidth > maxContinuousUlBandwidth)
+    {
+      maxContinuousUlBandwidth = tmpMinBandwidth;
+      ffrRbStartOffset = tmpFfrRbStartOffset;
+    }
+
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
   uint16_t rbStart = 0;
+  rbStart = ffrRbStartOffset;
   std::vector <struct RachListElement_s>::iterator itRach;
   for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
     {
@@ -702,7 +767,7 @@
       uint16_t rbLen = 1;
       uint16_t tbSizeBits = 0;
       // find lowest TB size that fits UL grant estimated size
-      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
+      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
         {
           rbLen++;
           tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
@@ -909,7 +974,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -927,7 +992,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1233,7 +1298,9 @@
                 {
                   if (rbgMap.at (i) == true)
                     continue;
-        
+                  if ((m_ffrSapProvider->IsDlRbgAvailableForUe (i, (*it).first)) == false)
+                    continue;
+
                   std::map <uint16_t, pssFlowPerf_t>::iterator itMax = tdUeSet.end ();
                   double metricMax = 0.0;
                   for (it = tdUeSet.begin (); it != tdUeSet.end (); it++)
@@ -1329,6 +1396,9 @@
                 {
                   if (rbgMap.at (i) == true)
                     continue;
+
+                  if ((m_ffrSapProvider->IsDlRbgAvailableForUe (i, (*it).first)) == false)
+                    continue;
         
                   std::map <uint16_t, pssFlowPerf_t>::iterator itMax = tdUeSet.end ();
                   double metricMax = 0.0;
@@ -1563,6 +1633,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
@@ -1644,6 +1716,7 @@
 PssFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
+  m_ffrSapProvider->ReportDlCqiInfo (params);
 
   for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
     {
@@ -1738,6 +1811,7 @@
   NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
 
   RefreshUlCqiMaps ();
+  m_ffrSapProvider->ReportUlCqiInfo (m_ueCqi);
 
   // Generate RBs map
   FfMacSchedSapUser::SchedUlConfigIndParameters ret;
@@ -1752,6 +1826,21 @@
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
 
   rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+
+  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+
+  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+        }
+    }
+
+  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
+  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
+
+
   // remove RACH allocation
   for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
     {
@@ -1863,7 +1952,9 @@
 
 
   // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
-  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
+
   if (rbPerFlow < 3)
     {
       rbPerFlow = 3;  // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
@@ -1917,6 +2008,7 @@
             }
         }
 
+      rbAllocated = 0;
       UlDciListElement_s uldci;
       uldci.m_rnti = (*it).first;
       uldci.m_rbLen = rbPerFlow;
@@ -1933,9 +2025,15 @@
                   free = false;
                   break;
                 }
+              if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
+                {
+                  free = false;
+                  break;
+                }
             }
           if (free)
             {
+        	  NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
               uldci.m_rbStart = rbAllocated;
 
               for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
@@ -1964,13 +2062,14 @@
       if (!allocated)
         {
           // unable to allocate new resource: finish scheduling
-          m_nextRntiUl = (*it).first;
-          if (ret.m_dciList.size () > 0)
-            {
-              m_schedSapUser->SchedUlConfigInd (ret);
-            }
-          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
-          return;
+//          m_nextRntiUl = (*it).first;
+//          if (ret.m_dciList.size () > 0)
+//            {
+//              m_schedSapUser->SchedUlConfigInd (ret);
+//            }
+//          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
+//          return;
+    	  break;
         }
 
 
--- a/src/lte/model/pss-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/pss-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -30,7 +30,7 @@
 #include <map>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -102,6 +102,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class PssSchedulerMemberCschedSapProvider;
   friend class PssSchedulerMemberSchedSapProvider;
 
@@ -248,6 +252,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/rem-spectrum-phy.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/rem-spectrum-phy.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -38,10 +38,12 @@
 NS_OBJECT_ENSURE_REGISTERED (RemSpectrumPhy);
 
 RemSpectrumPhy::RemSpectrumPhy ()
-  : m_mobility (0),    
+  : m_mobility (0),
     m_referenceSignalPower (0),
     m_sumPower (0),
-    m_active (true)
+    m_active (true),
+    m_useDataChannel (false),
+    m_rbId (-1)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -67,7 +69,7 @@
   static TypeId tid = TypeId ("ns3::RemSpectrumPhy")
     .SetParent<SpectrumPhy> ()
     .AddConstructor<RemSpectrumPhy> ()
-    ;
+  ;
   return tid;
 }
 
@@ -125,15 +127,50 @@
 
   if (m_active)
     {
-      Ptr<LteSpectrumSignalParametersDlCtrlFrame> lteDlCtrlRxParams = DynamicCast<LteSpectrumSignalParametersDlCtrlFrame> (params);
-      if (lteDlCtrlRxParams!=0)
+      if (m_useDataChannel)
         {
-          double power = Integral (*(params->psd));
-                               
-          m_sumPower += power;
-          if (power > m_referenceSignalPower)
+          Ptr<LteSpectrumSignalParametersDataFrame> lteDlDataRxParams = DynamicCast<LteSpectrumSignalParametersDataFrame> (params);
+          if (lteDlDataRxParams != 0)
             {
-              m_referenceSignalPower = power;
+              NS_LOG_DEBUG ("StartRx data");
+              double power = 0;
+              if (m_rbId >= 0)
+                {
+                  power = (*(params->psd))[m_rbId] * 180000;
+                }
+              else
+                {
+                  power = Integral (*(params->psd));
+                }
+
+              m_sumPower += power;
+              if (power > m_referenceSignalPower)
+                {
+                  m_referenceSignalPower = power;
+                }
+            }
+        }
+      else
+        {
+          Ptr<LteSpectrumSignalParametersDlCtrlFrame> lteDlCtrlRxParams = DynamicCast<LteSpectrumSignalParametersDlCtrlFrame> (params);
+          if (lteDlCtrlRxParams != 0)
+            {
+              NS_LOG_DEBUG ("StartRx control");
+              double power = 0;
+              if (m_rbId >= 0)
+                {
+                  power = (*(params->psd))[m_rbId] * 180000;
+                }
+              else
+                {
+                  power = Integral (*(params->psd));
+                }
+
+              m_sumPower += power;
+              if (power > m_referenceSignalPower)
+                {
+                  m_referenceSignalPower = power;
+                }
             }
         }
     }
@@ -171,5 +208,17 @@
   m_sumPower = 0;
 }
 
+void
+RemSpectrumPhy::SetUseDataChannel (bool value)
+{
+  m_useDataChannel = value;
+}
+
+void
+RemSpectrumPhy::SetRbId (int32_t rbId)
+{
+  m_rbId = rbId;
+}
+
 
 } // namespace ns3
--- a/src/lte/model/rem-spectrum-phy.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/rem-spectrum-phy.h	Fri Sep 05 01:12:55 2014 +0200
@@ -82,9 +82,9 @@
    */
   double GetSinr (double noisePower);
 
-  /** 
+  /**
    * make StartRx a no-op from now on, and mark instance as inactive
-   * 
+   *
    */
   void Deactivate ();
 
@@ -100,6 +100,20 @@
    */
   void Reset ();
 
+  /**
+   * set usage of DataChannel
+   *
+   * \param value if true, data channel signal will be processed, control signal otherwise
+   */
+  void SetUseDataChannel (bool value);
+
+  /**
+   * set RB Id
+   *
+   * \param rbId Resource Block Id which will be processed
+   */
+  void SetRbId (int32_t rbId);
+
 private:
   Ptr<MobilityModel> m_mobility;
   Ptr<const SpectrumModel> m_rxSpectrumModel;
@@ -109,6 +123,9 @@
 
   bool m_active;
 
+  bool m_useDataChannel;
+  int32_t m_rbId;
+
 };
 
 
--- a/src/lte/model/rr-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/rr-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -298,6 +298,18 @@
 }
 
 void
+RrFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+RrFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 RrFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -847,7 +859,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -865,7 +877,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1181,6 +1193,9 @@
           newDci.m_ndi.push_back (1);
           newDci.m_rv.push_back (0);
         }
+
+      newDci.m_tpc = 1; //1 is mapped to 0 in Accumulated Mode and to -1 in Absolute Mode
+
       newEl.m_dci = newDci;
       if (m_harqOn == true)
         {
--- a/src/lte/model/rr-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/rr-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -29,6 +29,7 @@
 #include <map>
 #include <ns3/lte-common.h>
 #include <ns3/lte-amc.h>
+#include <ns3/lte-ffr-sap.h>
 
 #define HARQ_PROC_NUM 8
 #define HARQ_DL_TIMEOUT 11
@@ -80,6 +81,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class RrSchedulerMemberCschedSapProvider;
   friend class RrSchedulerMemberSchedSapProvider;
 
@@ -205,6 +210,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/tdbet-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/tdbet-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -296,6 +296,18 @@
 }
 
 void
+TdBetFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+TdBetFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 TdBetFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -881,7 +893,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -899,7 +911,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1162,6 +1174,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = 1; //1 is mapped to 0 in Accumulated Mode and to -1 in Absolute Mode
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
--- a/src/lte/model/tdbet-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/tdbet-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -30,7 +30,7 @@
 #include <map>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -94,6 +94,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class TdBetSchedulerMemberCschedSapProvider;
   friend class TdBetSchedulerMemberSchedSapProvider;
 
@@ -240,6 +244,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/tdmt-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/tdmt-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -295,6 +295,18 @@
 }
 
 void
+TdMtFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+TdMtFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 TdMtFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -870,7 +882,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -888,7 +900,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1186,6 +1198,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = 1; //1 is mapped to 0 in Accumulated Mode and to -1 in Absolute Mode
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
--- a/src/lte/model/tdmt-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/tdmt-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -31,7 +31,7 @@
 #include <set>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -86,6 +86,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class TdMtSchedulerMemberCschedSapProvider;
   friend class TdMtSchedulerMemberSchedSapProvider;
 
@@ -232,6 +236,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/tdtbfq-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/tdtbfq-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -223,6 +223,8 @@
   m_amc = CreateObject <LteAmc> ();
   m_cschedSapProvider = new TdTbfqSchedulerMemberCschedSapProvider (this);
   m_schedSapProvider = new TdTbfqSchedulerMemberSchedSapProvider (this);
+  m_ffrSapProvider = 0;
+  m_ffrSapUser = new MemberLteFfrSapUser<TdTbfqFfMacScheduler> (this);
 }
 
 TdTbfqFfMacScheduler::~TdTbfqFfMacScheduler ()
@@ -243,6 +245,7 @@
   m_ulHarqProcessesDciBuffer.clear ();
   delete m_cschedSapProvider;
   delete m_schedSapProvider;
+  delete m_ffrSapUser;
 }
 
 TypeId
@@ -318,6 +321,18 @@
 }
 
 void
+TdTbfqFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+TdTbfqFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 TdTbfqFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -692,6 +707,16 @@
   uint16_t rbgAllocatedNum = 0;
   std::set <uint16_t> rntiAllocated;
   rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
+
+  rbgMap = m_ffrSapProvider->GetAvailableDlRbg ();
+  for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbgAllocatedNum++;
+        }
+    }
+
   FfMacSchedSapUser::SchedDlConfigIndParameters ret;
 
   //   update UL HARQ proc id
@@ -702,8 +727,48 @@
     }
 
   // RACH Allocation
+  uint16_t rbAllocatedNum = 0;
+  std::vector <bool> ulRbMap;
+  ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+  ulRbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+  uint8_t maxContinuousUlBandwidth = 0;
+  uint8_t tmpMinBandwidth = 0;
+  uint16_t ffrRbStartOffset = 0;
+  uint16_t tmpFfrRbStartOffset = 0;
+  uint16_t index = 0;
+
+  for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+          if (tmpMinBandwidth > maxContinuousUlBandwidth)
+            {
+              maxContinuousUlBandwidth = tmpMinBandwidth;
+              ffrRbStartOffset = tmpFfrRbStartOffset;
+            }
+          tmpMinBandwidth = 0;
+        }
+      else
+        {
+          if (tmpMinBandwidth == 0)
+            {
+              tmpFfrRbStartOffset = index;
+            }
+          tmpMinBandwidth++;
+        }
+      index++;
+    }
+
+  if (tmpMinBandwidth > maxContinuousUlBandwidth)
+    {
+      maxContinuousUlBandwidth = tmpMinBandwidth;
+      ffrRbStartOffset = tmpFfrRbStartOffset;
+    }
+
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
   uint16_t rbStart = 0;
+  rbStart = ffrRbStartOffset;
   std::vector <struct RachListElement_s>::iterator itRach;
   for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
     {
@@ -718,7 +783,7 @@
       uint16_t rbLen = 1;
       uint16_t tbSizeBits = 0;
       // find lowest TB size that fits UL grant estimated size
-      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
+      while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
         {
           rbLen++;
           tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
@@ -925,7 +990,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -943,7 +1008,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1128,6 +1193,9 @@
           if ( rbgMap.at (i) == true) // this RBG is allocated in RACH procedure
             continue;
 
+          if ((m_ffrSapProvider->IsDlRbgAvailableForUe (i, (*itMax).first)) == false)
+            continue;
+
           tempMap.push_back (i);
           rbgMap.at (i) = true;
         }
@@ -1266,6 +1334,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
@@ -1331,6 +1401,7 @@
 TdTbfqFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
+  m_ffrSapProvider->ReportDlCqiInfo (params);
 
   for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
     {
@@ -1425,6 +1496,7 @@
   NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
 
   RefreshUlCqiMaps ();
+  m_ffrSapProvider->ReportUlCqiInfo (m_ueCqi);
 
   // Generate RBs map
   FfMacSchedSapUser::SchedUlConfigIndParameters ret;
@@ -1439,6 +1511,20 @@
   m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
 
   rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
+
+  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
+
+  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
+    {
+      if ((*it) == true )
+        {
+          rbAllocatedNum++;
+        }
+    }
+
+  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
+  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
+
   // remove RACH allocation
   for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
     {
@@ -1550,7 +1636,9 @@
 
 
   // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
-  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
+  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
+
   if (rbPerFlow < 3)
     {
       rbPerFlow = 3;  // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
@@ -1604,6 +1692,7 @@
             }
         }
 
+      rbAllocated = 0;
       UlDciListElement_s uldci;
       uldci.m_rnti = (*it).first;
       uldci.m_rbLen = rbPerFlow;
@@ -1620,9 +1709,15 @@
                   free = false;
                   break;
                 }
+              if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
+                {
+                  free = false;
+                  break;
+                }
             }
           if (free)
             {
+        	  NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
               uldci.m_rbStart = rbAllocated;
 
               for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
@@ -1651,13 +1746,14 @@
       if (!allocated)
         {
           // unable to allocate new resource: finish scheduling
-          m_nextRntiUl = (*it).first;
-          if (ret.m_dciList.size () > 0)
-            {
-              m_schedSapUser->SchedUlConfigInd (ret);
-            }
-          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
-          return;
+//          m_nextRntiUl = (*it).first;
+//          if (ret.m_dciList.size () > 0)
+//            {
+//              m_schedSapUser->SchedUlConfigInd (ret);
+//            }
+//          m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
+//          return;
+    	  break;
         }
 
 
--- a/src/lte/model/tdtbfq-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/tdtbfq-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -30,7 +30,7 @@
 #include <map>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -101,6 +101,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class TdTbfqSchedulerMemberCschedSapProvider;
   friend class TdTbfqSchedulerMemberSchedSapProvider;
 
@@ -247,6 +251,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- a/src/lte/model/tta-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/tta-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -295,6 +295,18 @@
 }
 
 void
+TtaFfMacScheduler::SetLteFfrSapProvider (LteFfrSapProvider* s)
+{
+  m_ffrSapProvider = s;
+}
+
+LteFfrSapUser*
+TtaFfMacScheduler::GetLteFfrSapUser ()
+{
+  return m_ffrSapUser;
+}
+
+void
 TtaFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
 {
   NS_LOG_FUNCTION (this);
@@ -870,7 +882,7 @@
                       dciRbg.at (j) = rbgId;
                       j++;
                     }
-                  rbgId++;
+                  rbgId = (rbgId + 1) % rbgNum;
                 }
               if (j == dciRbg.size ())
                 {
@@ -888,7 +900,7 @@
               else
                 {
                   // HARQ retx cannot be performed on this TTI -> store it
-                  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
+                  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
                   NS_LOG_INFO (this << " No resource for this retx -> buffer it");
                 }
             }
@@ -1265,6 +1277,8 @@
           newDci.m_rv.push_back (0);
         }
 
+      newDci.m_tpc = 1; //1 is mapped to 0 in Accumulated Mode and to -1 in Absolute Mode
+
       newEl.m_dci = newDci;
 
       if (m_harqOn == true)
--- a/src/lte/model/tta-ff-mac-scheduler.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/model/tta-ff-mac-scheduler.h	Fri Sep 05 01:12:55 2014 +0200
@@ -31,7 +31,7 @@
 #include <set>
 #include <ns3/nstime.h>
 #include <ns3/lte-amc.h>
-
+#include <ns3/lte-ffr-sap.h>
 
 // value for SINR outside the range defined by FF-API, used to indicate that there
 // is no CQI for this element
@@ -86,6 +86,10 @@
   virtual FfMacCschedSapProvider* GetFfMacCschedSapProvider ();
   virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider ();
 
+  // FFR SAPs
+  virtual void SetLteFfrSapProvider (LteFfrSapProvider* s);
+  virtual LteFfrSapUser* GetLteFfrSapUser ();
+
   friend class TtaSchedulerMemberCschedSapProvider;
   friend class TtaSchedulerMemberSchedSapProvider;
 
@@ -232,6 +236,9 @@
   FfMacCschedSapProvider* m_cschedSapProvider;
   FfMacSchedSapProvider* m_schedSapProvider;
 
+  // FFR SAPs
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
 
   // Internal parameters
   FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-ffr-simple.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,326 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include "lte-ffr-simple.h"
+#include <ns3/log.h>
+#include "ns3/lte-rrc-sap.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteFfrSimple");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteFfrSimple);
+
+
+LteFfrSimple::LteFfrSimple ()
+  : m_ffrSapUser (0),
+    m_ffrRrcSapUser (0),
+    m_dlOffset (0),
+    m_dlSubBand (0),
+    m_ulOffset (0),
+    m_ulSubBand (0),
+    m_measId (0),
+    m_changePdschConfigDedicated (false),
+    m_tpc (1),
+    m_tpcNum (0),
+    m_acculumatedMode (false)
+{
+  NS_LOG_FUNCTION (this);
+  m_ffrSapProvider = new MemberLteFfrSapProvider<LteFfrSimple> (this);
+  m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFfrSimple> (this);
+}
+
+
+LteFfrSimple::~LteFfrSimple ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteFfrSimple::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ffrSapProvider;
+  delete m_ffrRrcSapProvider;
+}
+
+
+TypeId
+LteFfrSimple::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::LteFfrSimple")
+    .SetParent<LteFfrAlgorithm> ()
+    .AddConstructor<LteFfrSimple> ()
+    .AddAttribute ("UlSubBandOffset",
+                   "Uplink Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFfrSimple::m_ulOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("UlSubBandwidth",
+                   "Uplink Transmission SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (25),
+                   MakeUintegerAccessor (&LteFfrSimple::m_ulSubBand),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlSubBandOffset",
+                   "Downlink Offset in number of Resource Block Groups",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&LteFfrSimple::m_dlOffset),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("DlSubBandwidth",
+                   "Downlink Transmission SubBandwidth Configuration in number of Resource Block Groups",
+                   UintegerValue (12),
+                   MakeUintegerAccessor (&LteFfrSimple::m_dlSubBand),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddTraceSource ("ChangePdschConfigDedicated",
+                     "trace fired upon change of PdschConfigDedicated",
+                     MakeTraceSourceAccessor (&LteFfrSimple::m_changePdschConfigDedicatedTrace))
+  ;
+  return tid;
+}
+
+
+void
+LteFfrSimple::SetLteFfrSapUser (LteFfrSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrSapUser = s;
+}
+
+
+LteFfrSapProvider*
+LteFfrSimple::GetLteFfrSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrSapProvider;
+}
+
+void
+LteFfrSimple::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_ffrRrcSapUser = s;
+}
+
+
+LteFfrRrcSapProvider*
+LteFfrSimple::GetLteFfrRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ffrRrcSapProvider;
+}
+
+
+void
+LteFfrSimple::DoInitialize ()
+{
+  NS_LOG_FUNCTION (this);
+  LteFfrAlgorithm::DoInitialize ();
+
+  NS_LOG_LOGIC (this << " requesting Event A4 measurements"
+                     << " (threshold = 0" << ")");
+  LteRrcSap::ReportConfigEutra reportConfig;
+  reportConfig.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1;
+  reportConfig.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ;
+  reportConfig.threshold1.range = 0;
+  reportConfig.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRQ;
+  reportConfig.reportInterval = LteRrcSap::ReportConfigEutra::MS120;
+  m_measId = m_ffrRrcSapUser->AddUeMeasReportConfigForFfr (reportConfig);
+
+  m_pdschConfigDedicated.pa = LteRrcSap::PdschConfigDedicated::dB0;
+}
+
+void
+LteFfrSimple::Reconfigure ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteFfrSimple::ChangePdschConfigDedicated (bool change)
+{
+  m_changePdschConfigDedicated = change;
+}
+
+void
+LteFfrSimple::SetPdschConfigDedicated (LteRrcSap::PdschConfigDedicated pdschConfigDedicated)
+{
+  m_pdschConfigDedicated = pdschConfigDedicated;
+}
+
+void
+LteFfrSimple::SetTpc (uint32_t tpc, uint32_t num, bool acculumatedMode)
+{
+  m_tpc = tpc;
+  m_tpcNum = num;
+  m_acculumatedMode = acculumatedMode;
+}
+
+std::vector <bool>
+LteFfrSimple::DoGetAvailableDlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_dlRbgMap.empty ())
+    {
+      int rbgSize = GetRbgSize (m_dlBandwidth);
+      m_dlRbgMap.resize (m_dlBandwidth / rbgSize, true);
+
+      for (uint8_t i = m_dlOffset; i < (m_dlOffset + m_dlSubBand); i++)
+        {
+          m_dlRbgMap[i] = false;
+
+        }
+    }
+
+  return m_dlRbgMap;
+}
+
+bool
+LteFfrSimple::DoIsDlRbgAvailableForUe (int i, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  return true;
+}
+
+std::vector <bool>
+LteFfrSimple::DoGetAvailableUlRbg ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_ulRbgMap.empty ())
+    {
+      m_ulRbgMap.resize (m_ulBandwidth, true);
+
+      for (uint8_t i = m_ulOffset; i < (m_ulOffset + m_ulSubBand); i++)
+        {
+          m_ulRbgMap[i] = false;
+        }
+    }
+
+  return m_ulRbgMap;
+}
+
+bool
+LteFfrSimple::DoIsUlRbgAvailableForUe (int i, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  return true;
+}
+
+void
+LteFfrSimple::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteFfrSimple::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteFfrSimple::DoReportUlCqiInfo (std::map <uint16_t, std::vector <double> > ulCqiMap)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+uint8_t
+LteFfrSimple::DoGetTpc (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_acculumatedMode)
+    {
+      if (m_tpcNum > 0)
+        {
+          m_tpcNum--;
+          return m_tpc;
+        }
+      else
+        {
+          return 1;
+        }
+    }
+  else
+    {
+      return m_tpc;
+    }
+
+  return 1; // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
+}
+
+uint8_t
+LteFfrSimple::DoGetMinContinuousUlBandwidth ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_ulBandwidth;
+}
+
+void
+LteFfrSimple::DoReportUeMeas (uint16_t rnti,
+                              LteRrcSap::MeasResults measResults)
+{
+  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
+
+  std::map<uint16_t, LteRrcSap::PdschConfigDedicated>::iterator it;
+
+  it = m_ues.find (rnti);
+
+  if (it == m_ues.end ())
+    {
+      LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+      pdschConfigDedicated.pa = LteRrcSap::PdschConfigDedicated::dB0;
+      m_ues.insert (std::pair<uint16_t, LteRrcSap::PdschConfigDedicated> (rnti,
+                                                                          pdschConfigDedicated));
+    }
+
+  if (m_changePdschConfigDedicated)
+    {
+      UpdatePdschConfigDedicated ();
+    }
+}
+
+void
+LteFfrSimple::UpdatePdschConfigDedicated ()
+{
+  NS_LOG_FUNCTION (this);
+
+  std::map<uint16_t, LteRrcSap::PdschConfigDedicated>::iterator it;
+  for (it = m_ues.begin (); it != m_ues.end (); it++)
+    {
+      if (it->second.pa != m_pdschConfigDedicated.pa)
+        {
+          m_changePdschConfigDedicatedTrace (it->first, m_pdschConfigDedicated.pa);
+          LteRrcSap::PdschConfigDedicated pdschConfigDedicated = m_pdschConfigDedicated;
+          m_ffrRrcSapUser->SetPdschConfigDedicated (it->first, pdschConfigDedicated );
+        }
+    }
+}
+
+void
+LteFfrSimple::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-ffr-simple.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,137 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_FFR_SIMPLE_H
+#define LTE_FFR_SIMPLE_H
+
+#include <ns3/lte-ffr-algorithm.h>
+#include <ns3/lte-ffr-sap.h>
+#include <ns3/lte-ffr-rrc-sap.h>
+#include <ns3/lte-rrc-sap.h>
+
+#include <ns3/traced-callback.h>
+#include <map>
+
+namespace ns3 {
+
+
+/**
+ * \brief Simple Frequency Reuse algorithm implementation which uses only 1 sub-band.
+ *                Used to test Downlink Power Allocation. When Simple FR receives UE measurements
+ *                it immediately call functions to change PdschConfigDedicated (i.e. P_A) value for
+ *                this UE.
+ */
+class LteFfrSimple : public LteFfrAlgorithm
+{
+public:
+  /**
+   * \brief Creates a trivial ffr algorithm instance.
+   */
+  LteFfrSimple ();
+
+  virtual ~LteFfrSimple ();
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  void ChangePdschConfigDedicated (bool change);
+  void SetPdschConfigDedicated (LteRrcSap::PdschConfigDedicated pdschConfigDedicated);
+
+  void SetTpc (uint32_t tpc, uint32_t num, bool acculumatedMode);
+
+  // inherited from LteFfrAlgorithm
+  virtual void SetLteFfrSapUser (LteFfrSapUser* s);
+  virtual LteFfrSapProvider* GetLteFfrSapProvider ();
+
+  virtual void SetLteFfrRrcSapUser (LteFfrRrcSapUser* s);
+  virtual LteFfrRrcSapProvider* GetLteFfrRrcSapProvider ();
+
+  // let the forwarder class access the protected and private members
+  friend class MemberLteFfrSapProvider<LteFfrSimple>;
+  friend class MemberLteFfrRrcSapProvider<LteFfrSimple>;
+
+protected:
+  // inherited from Object
+  virtual void DoInitialize ();
+  virtual void DoDispose ();
+
+  virtual void Reconfigure ();
+
+  // FFR SAP PROVIDER IMPLEMENTATION
+  virtual std::vector <bool> DoGetAvailableDlRbg ();
+  virtual bool DoIsDlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual std::vector <bool> DoGetAvailableUlRbg ();
+  virtual bool DoIsUlRbgAvailableForUe (int i, uint16_t rnti);
+  virtual void DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params);
+  virtual void DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap );
+  virtual uint8_t DoGetTpc (uint16_t rnti);
+  virtual uint8_t DoGetMinContinuousUlBandwidth ();
+
+  // FFR SAP RRC PROVIDER IMPLEMENTATION
+  virtual void DoReportUeMeas (uint16_t rnti, LteRrcSap::MeasResults measResults);
+  virtual void DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params);
+
+private:
+
+  void UpdatePdschConfigDedicated ();
+
+  // FFR SAP
+  LteFfrSapUser* m_ffrSapUser;
+  LteFfrSapProvider* m_ffrSapProvider;
+
+  // FFR RRF SAP
+  LteFfrRrcSapUser* m_ffrRrcSapUser;
+  LteFfrRrcSapProvider* m_ffrRrcSapProvider;
+
+  uint8_t m_dlOffset;
+  uint8_t m_dlSubBand;
+
+  uint8_t m_ulOffset;
+  uint8_t m_ulSubBand;
+
+  std::vector <bool> m_dlRbgMap;
+  std::vector <bool> m_ulRbgMap;
+
+  std::map <uint16_t, LteRrcSap::PdschConfigDedicated> m_ues;
+
+  // The expected measurement identity
+  uint8_t m_measId;
+
+  bool m_changePdschConfigDedicated;
+
+  LteRrcSap::PdschConfigDedicated m_pdschConfigDedicated;
+
+  TracedCallback<uint16_t, uint8_t> m_changePdschConfigDedicatedTrace;
+
+
+  //Uplink Power Control
+  uint32_t m_tpc;
+  uint32_t m_tpcNum;
+  bool m_acculumatedMode;
+
+}; // end of class LteFfrSimple
+
+
+} // end of namespace ns3
+
+
+#endif /* LTE_FFR_SIMPLE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-simple-spectrum-phy.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,170 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include <ns3/log.h>
+#include <cmath>
+#include <ns3/simulator.h>
+#include <ns3/antenna-model.h>
+#include "lte-simple-spectrum-phy.h"
+#include "ns3/lte-spectrum-signal-parameters.h"
+#include "ns3/lte-net-device.h"
+#include "ns3/lte-phy-tag.h"
+#include <ns3/boolean.h>
+#include <ns3/double.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteSimpleSpectrumPhy");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteSimpleSpectrumPhy);
+
+LteSimpleSpectrumPhy::LteSimpleSpectrumPhy ()
+  : m_cellId (0)
+{
+}
+
+
+LteSimpleSpectrumPhy::~LteSimpleSpectrumPhy ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void LteSimpleSpectrumPhy::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  m_channel = 0;
+  m_mobility = 0;
+  m_device = 0;
+  SpectrumPhy::DoDispose ();
+}
+
+
+TypeId
+LteSimpleSpectrumPhy::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LteSimpleSpectrumPhy")
+    .SetParent<SpectrumPhy> ()
+    .AddTraceSource ("RxStart",
+                     "Data reception start",
+                     MakeTraceSourceAccessor (&LteSimpleSpectrumPhy::m_rxStart))
+  ;
+  return tid;
+}
+
+
+
+Ptr<NetDevice>
+LteSimpleSpectrumPhy::GetDevice ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_device;
+}
+
+
+Ptr<MobilityModel>
+LteSimpleSpectrumPhy::GetMobility ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_mobility;
+}
+
+
+void
+LteSimpleSpectrumPhy::SetDevice (Ptr<NetDevice> d)
+{
+  NS_LOG_FUNCTION (this << d);
+  m_device = d;
+}
+
+
+void
+LteSimpleSpectrumPhy::SetMobility (Ptr<MobilityModel> m)
+{
+  NS_LOG_FUNCTION (this << m);
+  m_mobility = m;
+}
+
+
+void
+LteSimpleSpectrumPhy::SetChannel (Ptr<SpectrumChannel> c)
+{
+  NS_LOG_FUNCTION (this << c);
+  m_channel = c;
+}
+
+Ptr<const SpectrumModel>
+LteSimpleSpectrumPhy::GetRxSpectrumModel () const
+{
+  return m_rxSpectrumModel;
+}
+
+
+Ptr<AntennaModel>
+LteSimpleSpectrumPhy::GetRxAntenna ()
+{
+  return m_antenna;
+}
+
+void
+LteSimpleSpectrumPhy::StartRx (Ptr<SpectrumSignalParameters> spectrumRxParams)
+{
+  NS_LOG_DEBUG ("LteSimpleSpectrumPhy::StartRx");
+
+  NS_LOG_FUNCTION (this << spectrumRxParams);
+  Ptr <const SpectrumValue> rxPsd = spectrumRxParams->psd;
+  Time duration = spectrumRxParams->duration;
+
+  // the device might start RX only if the signal is of a type
+  // understood by this device - in this case, an LTE signal.
+  Ptr<LteSpectrumSignalParametersDataFrame> lteDataRxParams = DynamicCast<LteSpectrumSignalParametersDataFrame> (spectrumRxParams);
+  if (lteDataRxParams != 0)
+    {
+      if ( m_cellId > 0 )
+        {
+          if (m_cellId == lteDataRxParams->cellId)
+            {
+              m_rxStart (rxPsd);
+            }
+        }
+      else
+        {
+          m_rxStart (rxPsd);
+        }
+    }
+}
+
+void
+LteSimpleSpectrumPhy::SetRxSpectrumModel (Ptr<const SpectrumModel> model)
+{
+  NS_LOG_FUNCTION (this);
+  m_rxSpectrumModel = model;
+}
+
+void
+LteSimpleSpectrumPhy::SetCellId (uint16_t cellId)
+{
+  NS_LOG_FUNCTION (this);
+  m_cellId = cellId;
+}
+
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-simple-spectrum-phy.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,91 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_SIMPLE_SPECTRUM_PHY_H
+#define LTE_SIMPLE_SPECTRUM_PHY_H
+
+#include <ns3/event-id.h>
+#include <ns3/spectrum-value.h>
+#include <ns3/mobility-model.h>
+#include <ns3/net-device.h>
+#include <ns3/spectrum-phy.h>
+#include <ns3/spectrum-channel.h>
+#include <ns3/traced-callback.h>
+
+namespace ns3 {
+
+/**
+ * \ingroup lte
+ *
+ * The LteSimpleSpectrumPhy models the physical layer of LTE
+ * This class is used to test Frequency Reuse Algorithms,
+ * it allow to get SpectrumValue from channel and pass it to
+ * test script by trace mechanism.
+ * When m_cellId is 0, all received signals will be traced,
+ * if m_cellId > 0, only signals from specified Cell will be traced.
+ *
+ */
+
+class LteSimpleSpectrumPhy : public SpectrumPhy
+{
+
+public:
+  LteSimpleSpectrumPhy ();
+  virtual ~LteSimpleSpectrumPhy ();
+
+  // inherited from Object
+  static TypeId GetTypeId (void);
+  virtual void DoDispose ();
+
+  // inherited from SpectrumPhy
+  void SetChannel (Ptr<SpectrumChannel> c);
+  void SetMobility (Ptr<MobilityModel> m);
+  void SetDevice (Ptr<NetDevice> d);
+  Ptr<MobilityModel> GetMobility ();
+  Ptr<NetDevice> GetDevice ();
+  Ptr<const SpectrumModel> GetRxSpectrumModel () const;
+  Ptr<AntennaModel> GetRxAntenna ();
+  void StartRx (Ptr<SpectrumSignalParameters> params);
+
+  void SetRxSpectrumModel (Ptr<const SpectrumModel> model);
+
+  void SetCellId (uint16_t cellId);
+
+private:
+  Ptr<MobilityModel> m_mobility;
+  Ptr<AntennaModel> m_antenna;
+  Ptr<NetDevice> m_device;
+  Ptr<SpectrumChannel> m_channel;
+  Ptr<const SpectrumModel> m_rxSpectrumModel;
+
+  uint16_t m_cellId;
+
+  TracedCallback< Ptr<const SpectrumValue> > m_rxStart;
+};
+
+
+
+
+
+
+}
+
+#endif /* LTE_SIMPLE_SPECTRUM_PHY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-cqi-generation.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,208 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include <ns3/simulator.h>
+#include <ns3/log.h>
+#include <ns3/callback.h>
+#include <ns3/config.h>
+#include <ns3/string.h>
+#include <ns3/double.h>
+#include <ns3/enum.h>
+#include <ns3/boolean.h>
+#include <ns3/pointer.h>
+#include "ns3/ff-mac-scheduler.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/lte-helper.h"
+
+#include "lte-test-cqi-generation.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteCqiGenerationTest");
+
+using namespace ns3;
+
+void
+LteTestDlSchedulingCallback (LteCqiGenerationTestCase *testcase, std::string path,
+                             uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
+                             uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2)
+{
+  testcase->DlScheduling (frameNo, subframeNo, rnti, mcsTb1, sizeTb1, mcsTb2, sizeTb2);
+}
+
+void
+LteTestUlSchedulingCallback (LteCqiGenerationTestCase *testcase, std::string path,
+                             uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
+                             uint8_t mcs, uint16_t sizeTb)
+{
+  testcase->UlScheduling (frameNo, subframeNo, rnti, mcs, sizeTb);
+}
+
+
+/**
+ * TestSuite
+ */
+
+LteCqiGenerationTestSuite::LteCqiGenerationTestSuite ()
+  : TestSuite ("lte-cqi-generation", SYSTEM)
+{
+//  LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_DEBUG);
+//  LogComponentEnable ("LteCqiGenerationTest", logLevel);
+  NS_LOG_INFO ("Creating LteCqiGenerationTestSuite");
+
+  AddTestCase (new LteCqiGenerationTestCase ("UsePdcchForCqiGeneration", false, 4, 2), TestCase::QUICK);
+  AddTestCase (new LteCqiGenerationTestCase ("UsePdschForCqiGeneration", true, 28, 2), TestCase::QUICK);
+
+}
+
+static LteCqiGenerationTestSuite lteCqiGenerationTestSuite;
+
+
+LteCqiGenerationTestCase::LteCqiGenerationTestCase (std::string name, bool usePdcchForCqiGeneration,
+                                                    uint16_t dlMcs, uint16_t ulMcs)
+  : TestCase ("Downlink Power Control: " + name),
+    m_dlMcs (dlMcs),
+    m_ulMcs (ulMcs)
+{
+  m_usePdcchForCqiGeneration = usePdcchForCqiGeneration;
+  NS_LOG_INFO ("Creating LteCqiGenerationTestCase");
+}
+
+LteCqiGenerationTestCase::~LteCqiGenerationTestCase ()
+{
+}
+
+void
+LteCqiGenerationTestCase::DlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
+                                        uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2)
+{
+  // need to allow for RRC connection establishment + CQI feedback reception
+  if (Simulator::Now () > MilliSeconds (35))
+    {
+//	  NS_LOG_UNCOND("DL MSC: " << (uint32_t)mcsTb1 << " expected DL MCS: " << (uint32_t)m_dlMcs);
+      NS_TEST_ASSERT_MSG_EQ ((uint32_t)mcsTb1, (uint32_t)m_dlMcs, "Wrong DL MCS ");
+    }
+}
+
+void
+LteCqiGenerationTestCase::UlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
+                                        uint8_t mcs, uint16_t sizeTb)
+{
+  // need to allow for RRC connection establishment + SRS transmission
+  if (Simulator::Now () > MilliSeconds (50))
+    {
+//	  NS_LOG_UNCOND("UL MSC: " << (uint32_t)mcs << " expected UL MCS: " << (uint32_t)m_ulMcs);
+      NS_TEST_ASSERT_MSG_EQ ((uint32_t)mcs, (uint32_t)m_ulMcs, "Wrong UL MCS");
+    }
+}
+
+void
+LteCqiGenerationTestCase::DoRun (void)
+{
+  NS_LOG_DEBUG ("LteCqiGenerationTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  Config::SetDefault ("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue (m_usePdcchForCqiGeneration));
+
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (true));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (true));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes1;
+  NodeContainer ueNodes2;
+  enbNodes.Create (2);
+  ueNodes1.Create (1);
+  ueNodes2.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2);
+
+  /*
+   * The topology is the following:
+   *
+   *  eNB1                        UE1 UE2                        eNB2
+   *    |                            |                            |
+   *    x -------------------------- x -------------------------- x
+   *                  500 m                       500 m
+   *
+   */
+
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));   // eNB1
+  positionAlloc->Add (Vector (1000, 0.0, 0.0)); // eNB2
+  positionAlloc->Add (Vector (500.0, 0.0, 0.0));  // UE1
+  positionAlloc->Add (Vector (500, 0.0, 0.0));  // UE2
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs1;
+  NetDeviceContainer ueDevs2;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+  lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrHardAlgorithm");
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandwidth", UintegerValue (12));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandwidth", UintegerValue (25));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandOffset", UintegerValue (12));
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandwidth", UintegerValue (12));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandwidth", UintegerValue (25));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
+
+  ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
+  ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs1, enbDevs.Get (0));
+  lteHelper->Attach (ueDevs2, enbDevs.Get (1));
+
+  // Activate an EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs1, bearer);
+  lteHelper->ActivateDataRadioBearer (ueDevs2, bearer);
+
+  Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
+                   MakeBoundCallback (&LteTestDlSchedulingCallback, this));
+
+  Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/UlScheduling",
+                   MakeBoundCallback (&LteTestUlSchedulingCallback, this));
+
+  Config::Connect ("/NodeList/1/DeviceList/0/LteEnbMac/DlScheduling",
+                   MakeBoundCallback (&LteTestDlSchedulingCallback, this));
+
+  Config::Connect ("/NodeList/1/DeviceList/0/LteEnbMac/UlScheduling",
+                   MakeBoundCallback (&LteTestUlSchedulingCallback, this));
+
+  Simulator::Stop (Seconds (1.100));
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-cqi-generation.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,57 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_TEST_CQI_GENERATION_H
+#define LTE_TEST_CQI_GENERATION_H
+
+#include "ns3/test.h"
+
+using namespace ns3;
+
+class LteCqiGenerationTestSuite : public TestSuite
+{
+public:
+  LteCqiGenerationTestSuite ();
+};
+
+class LteCqiGenerationTestCase : public TestCase
+{
+public:
+  LteCqiGenerationTestCase (std::string name, bool usePdcchForCqiGeneration,
+                            uint16_t dlMcs, uint16_t ulMcs);
+  virtual ~LteCqiGenerationTestCase ();
+
+  void DlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
+                     uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2);
+
+  void UlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
+                     uint8_t mcs, uint16_t sizeTb);
+
+private:
+  virtual void DoRun (void);
+
+  bool m_usePdcchForCqiGeneration;
+  uint16_t m_dlMcs;
+  uint16_t m_ulMcs;
+
+};
+
+#endif /* LTE_TEST_CQI_GENERATION_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-downlink-power-control.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,598 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include <ns3/simulator.h>
+#include <ns3/log.h>
+#include <ns3/callback.h>
+#include <ns3/config.h>
+#include <ns3/string.h>
+#include <ns3/double.h>
+#include <ns3/enum.h>
+#include <ns3/boolean.h>
+#include <ns3/pointer.h>
+
+#include "ns3/mobility-helper.h"
+#include "ns3/lte-helper.h"
+
+#include <ns3/ff-mac-scheduler.h>
+#include <ns3/lte-enb-net-device.h>
+#include <ns3/lte-enb-phy.h>
+#include <ns3/lte-enb-rrc.h>
+#include <ns3/lte-ue-net-device.h>
+#include <ns3/lte-ue-phy.h>
+#include <ns3/lte-ue-rrc.h>
+
+#include "lte-ffr-simple.h"
+#include "lte-test-sinr-chunk-processor.h"
+#include <ns3/lte-common.h>
+
+#include "lte-test-downlink-power-control.h"
+#include <ns3/lte-rrc-sap.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteDownlinkPowerControlTest");
+
+using namespace ns3;
+
+/**
+ * TestSuite
+ */
+
+LteDownlinkPowerControlTestSuite::LteDownlinkPowerControlTestSuite ()
+  : TestSuite ("lte-downlink-power-control", SYSTEM)
+{
+//  LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_DEBUG);
+//  LogComponentEnable ("LteDownlinkPowerControlTest", logLevel);
+  NS_LOG_INFO ("Creating LteDownlinkPowerControlTestSuite");
+
+  // Spectrum helper test
+  {
+    std::vector<int> activeRbs_txpowdB30nrb6run1earfcn500 (4);
+    activeRbs_txpowdB30nrb6run1earfcn500[0] = 0;
+    activeRbs_txpowdB30nrb6run1earfcn500[1] = 2;
+    activeRbs_txpowdB30nrb6run1earfcn500[2] = 3;
+    activeRbs_txpowdB30nrb6run1earfcn500[3] = 5;
+
+    uint16_t earfcn = 500;
+    uint8_t bw = 6;
+    double powerTx = 30;
+
+    std::map<int, double> powerTxMap;
+    double rbTxPower = powerTx;
+
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_6);
+    powerTxMap.insert (std::pair<int,double>(0, rbTxPower));
+
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(2, rbTxPower));
+
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB0);
+    powerTxMap.insert (std::pair<int,double>(3, rbTxPower));
+
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(5, rbTxPower));
+
+    SpectrumValue spectrumValue_txpowdB30nrb6run1earfcn500 (LteSpectrumValueHelper::GetSpectrumModel (500, 6));
+    spectrumValue_txpowdB30nrb6run1earfcn500[0] = 2.325820769916e-07;
+    spectrumValue_txpowdB30nrb6run1earfcn500[1] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb6run1earfcn500[2] = 4.640622533585e-07;
+    spectrumValue_txpowdB30nrb6run1earfcn500[3] = 9.259259259259e-07;
+    spectrumValue_txpowdB30nrb6run1earfcn500[4] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb6run1earfcn500[5] = 1.467493696723e-06;
+
+    AddTestCase (new LteDownlinkPowerControlSpectrumValueTestCase ("txpowdB30nrb6run1earfcn500_allRbPower",
+                                                                   earfcn, bw, powerTx,
+                                                                   powerTxMap, activeRbs_txpowdB30nrb6run1earfcn500,
+                                                                   spectrumValue_txpowdB30nrb6run1earfcn500), TestCase::QUICK);
+  }
+  {
+    //if power for RB not present, but RB is active, use powerTx
+    std::vector<int> activeRbs_txpowdB30nrb6run1earfcn500 (4);
+    activeRbs_txpowdB30nrb6run1earfcn500[0] = 0;
+    activeRbs_txpowdB30nrb6run1earfcn500[1] = 2;
+    activeRbs_txpowdB30nrb6run1earfcn500[2] = 3;
+    activeRbs_txpowdB30nrb6run1earfcn500[3] = 5;
+
+    uint16_t earfcn = 500;
+    uint8_t bw = 6;
+    double powerTx = 30;
+
+    std::map<int, double> powerTxMap;
+    double rbTxPower = powerTx;
+
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(2, rbTxPower));
+
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB0);
+    powerTxMap.insert (std::pair<int,double>(3, rbTxPower));
+
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(5, rbTxPower));
+
+    SpectrumValue spectrumValue_txpowdB30nrb6run1earfcn500 (LteSpectrumValueHelper::GetSpectrumModel (500, 6));
+    spectrumValue_txpowdB30nrb6run1earfcn500[0] = 9.259259259259e-07;
+    spectrumValue_txpowdB30nrb6run1earfcn500[1] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb6run1earfcn500[2] = 4.640622533585e-07;
+    spectrumValue_txpowdB30nrb6run1earfcn500[3] = 9.259259259259e-07;
+    spectrumValue_txpowdB30nrb6run1earfcn500[4] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb6run1earfcn500[5] = 1.467493696723e-06;
+
+    AddTestCase (new LteDownlinkPowerControlSpectrumValueTestCase ("txpowdB30nrb6run1earfcn500",
+                                                                   earfcn, bw, powerTx,
+                                                                   powerTxMap, activeRbs_txpowdB30nrb6run1earfcn500,
+                                                                   spectrumValue_txpowdB30nrb6run1earfcn500), TestCase::QUICK);
+  }
+  {
+    std::vector<int> activeRbs_txpowdB30nrb25run1earfcn500 (15);
+    activeRbs_txpowdB30nrb25run1earfcn500[0] = 0;
+    activeRbs_txpowdB30nrb25run1earfcn500[1] = 1;
+    activeRbs_txpowdB30nrb25run1earfcn500[2] = 2;
+    activeRbs_txpowdB30nrb25run1earfcn500[3] = 3;
+    activeRbs_txpowdB30nrb25run1earfcn500[4] = 7;
+    activeRbs_txpowdB30nrb25run1earfcn500[5] = 8;
+    activeRbs_txpowdB30nrb25run1earfcn500[6] = 9;
+    activeRbs_txpowdB30nrb25run1earfcn500[7] = 11;
+    activeRbs_txpowdB30nrb25run1earfcn500[8] = 13;
+    activeRbs_txpowdB30nrb25run1earfcn500[9] = 14;
+    activeRbs_txpowdB30nrb25run1earfcn500[10] = 18;
+    activeRbs_txpowdB30nrb25run1earfcn500[11] = 19;
+    activeRbs_txpowdB30nrb25run1earfcn500[12] = 20;
+    activeRbs_txpowdB30nrb25run1earfcn500[13] = 21;
+    activeRbs_txpowdB30nrb25run1earfcn500[14] = 24;
+
+    uint16_t earfcn = 500;
+    uint8_t bw = 25;
+    double powerTx = 30;
+
+    std::map<int, double> powerTxMap;
+    double rbTxPower = powerTx;
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(0, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_4dot77);
+    powerTxMap.insert (std::pair<int,double>(1, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_6);
+    powerTxMap.insert (std::pair<int,double>(2, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB1);
+    powerTxMap.insert (std::pair<int,double>(3, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(7, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(8, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(9, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_1dot77);
+    powerTxMap.insert (std::pair<int,double>(11, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(13, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(14, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB0);
+    powerTxMap.insert (std::pair<int,double>(18, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(19, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(20, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_4dot77);
+    powerTxMap.insert (std::pair<int,double>(21, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB3);
+    powerTxMap.insert (std::pair<int,double>(24, rbTxPower));
+
+
+    SpectrumValue spectrumValue_txpowdB30nrb25run1earfcn500 (LteSpectrumValueHelper::GetSpectrumModel (500, bw));
+    spectrumValue_txpowdB30nrb25run1earfcn500[0] = 1.113749408060e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[1] = 7.409475839182e-08;
+    spectrumValue_txpowdB30nrb25run1earfcn500[2] = 5.581969847799e-08;
+    spectrumValue_txpowdB30nrb25run1earfcn500[3] = 2.797612026209e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[4] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[5] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[6] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[7] = 3.521984872135e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[8] = 3.521984872135e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[9] = 3.521984872135e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[10] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[11] = 1.478384791559e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[12] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[13] = 3.521984872135e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[14] = 1.113749408060e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[15] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[16] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[17] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[18] = 2.222222222222e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[19] = 1.113749408060e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[20] = 1.113749408060e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[21] = 7.409475839182e-08;
+    spectrumValue_txpowdB30nrb25run1earfcn500[22] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[23] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[24] = 4.433916255486e-07;
+
+    AddTestCase (new LteDownlinkPowerControlSpectrumValueTestCase ("txpowdB30nrb25run1earfcn500_allRbPower",
+                                                                   earfcn, bw, powerTx,
+                                                                   powerTxMap, activeRbs_txpowdB30nrb25run1earfcn500,
+                                                                   spectrumValue_txpowdB30nrb25run1earfcn500), TestCase::QUICK);
+  }
+  {
+    //if power for RB not present, but RB is active, use powerTx
+    std::vector<int> activeRbs_txpowdB30nrb25run1earfcn500 (15);
+    activeRbs_txpowdB30nrb25run1earfcn500[0] = 0;
+    activeRbs_txpowdB30nrb25run1earfcn500[1] = 1;
+    activeRbs_txpowdB30nrb25run1earfcn500[2] = 2;
+    activeRbs_txpowdB30nrb25run1earfcn500[3] = 3;
+    activeRbs_txpowdB30nrb25run1earfcn500[4] = 7;
+    activeRbs_txpowdB30nrb25run1earfcn500[5] = 8;
+    activeRbs_txpowdB30nrb25run1earfcn500[6] = 9;
+    activeRbs_txpowdB30nrb25run1earfcn500[7] = 11;
+    activeRbs_txpowdB30nrb25run1earfcn500[8] = 13;
+    activeRbs_txpowdB30nrb25run1earfcn500[9] = 14;
+    activeRbs_txpowdB30nrb25run1earfcn500[10] = 18;
+    activeRbs_txpowdB30nrb25run1earfcn500[11] = 19;
+    activeRbs_txpowdB30nrb25run1earfcn500[12] = 20;
+    activeRbs_txpowdB30nrb25run1earfcn500[13] = 21;
+    activeRbs_txpowdB30nrb25run1earfcn500[14] = 24;
+
+    uint16_t earfcn = 500;
+    uint8_t bw = 25;
+    double powerTx = 30;
+
+    std::map<int, double> powerTxMap;
+    double rbTxPower = powerTx;
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(0, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_6);
+    powerTxMap.insert (std::pair<int,double>(2, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB1);
+    powerTxMap.insert (std::pair<int,double>(3, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(7, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(8, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB2);
+    powerTxMap.insert (std::pair<int,double>(13, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(14, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB0);
+    powerTxMap.insert (std::pair<int,double>(18, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB_3);
+    powerTxMap.insert (std::pair<int,double>(19, rbTxPower));
+    rbTxPower = CalculateRbTxPower (powerTx, LteRrcSap::PdschConfigDedicated::dB3);
+    powerTxMap.insert (std::pair<int,double>(24, rbTxPower));
+
+
+    SpectrumValue spectrumValue_txpowdB30nrb25run1earfcn500 (LteSpectrumValueHelper::GetSpectrumModel (500, bw));
+    spectrumValue_txpowdB30nrb25run1earfcn500[0] = 1.113749408060e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[1] = 2.222222222222e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[2] = 5.581969847799e-08;
+    spectrumValue_txpowdB30nrb25run1earfcn500[3] = 2.797612026209e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[4] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[5] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[6] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[7] = 3.521984872135e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[8] = 3.521984872135e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[9] = 2.222222222222e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[10] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[11] = 2.222222222222e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[12] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[13] = 3.521984872135e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[14] = 1.113749408060e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[15] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[16] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[17] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[18] = 2.222222222222e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[19] = 1.113749408060e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[20] = 2.222222222222e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[21] = 2.222222222222e-07;
+    spectrumValue_txpowdB30nrb25run1earfcn500[22] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[23] = 0.000000000000e+00;
+    spectrumValue_txpowdB30nrb25run1earfcn500[24] = 4.433916255486e-07;
+
+    AddTestCase (new LteDownlinkPowerControlSpectrumValueTestCase ("txpowdB30nrb25run1earfcn500",
+                                                                   earfcn, bw, powerTx,
+                                                                   powerTxMap, activeRbs_txpowdB30nrb25run1earfcn500,
+                                                                   spectrumValue_txpowdB30nrb25run1earfcn500), TestCase::QUICK);
+  }
+
+
+  // Downlink DATA and CONTROL channels power comparison
+  AddTestCase (new LteDownlinkPowerControlTestCase (false, LteRrcSap::PdschConfigDedicated::dB0,
+                                                    "DataCtrlPowerDifference_noChange"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlTestCase (true, LteRrcSap::PdschConfigDedicated::dB_6,
+                                                    "DataCtrlPowerDifference_dB_6"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlTestCase (true, LteRrcSap::PdschConfigDedicated::dB_4dot77,
+                                                    "DataCtrlPowerDifference_dB_4dot77"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlTestCase (true, LteRrcSap::PdschConfigDedicated::dB_3,
+                                                    "DataCtrlPowerDifference_dB_3"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlTestCase (true, LteRrcSap::PdschConfigDedicated::dB_1dot77,
+                                                    "DataCtrlPowerDifference_dB_1dot77"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlTestCase (true, LteRrcSap::PdschConfigDedicated::dB0,
+                                                    "DataCtrlPowerDifference_dB0"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlTestCase (true, LteRrcSap::PdschConfigDedicated::dB1,
+                                                    "DataCtrlPowerDifference_dB1"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlTestCase (true, LteRrcSap::PdschConfigDedicated::dB2,
+                                                    "DataCtrlPowerDifference_dB2"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlTestCase (true, LteRrcSap::PdschConfigDedicated::dB3,
+                                                    "DataCtrlPowerDifference_dB3"), TestCase::QUICK);
+
+
+  // RrcConnectionReconfiguration test
+  AddTestCase (new LteDownlinkPowerControlRrcConnectionReconfigurationTestCase (false, "RrcConnReconf-IdealRrc"), TestCase::QUICK);
+  AddTestCase (new LteDownlinkPowerControlRrcConnectionReconfigurationTestCase (true, "RrcConnReconf-RealRrc"), TestCase::QUICK);
+
+
+}
+
+double
+LteDownlinkPowerControlTestSuite::CalculateRbTxPower (double txPower, uint8_t pa)
+{
+  LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+  pdschConfigDedicated.pa = pa;
+  double rbTxpower = txPower + LteRrcSap::ConvertPdschConfigDedicated2Double (pdschConfigDedicated);
+
+  return rbTxpower;
+}
+
+static LteDownlinkPowerControlTestSuite lteDownlinkPowerControlTestSuite;
+
+
+/**
+ * TestCase Data
+ */
+
+LteDownlinkPowerControlSpectrumValueTestCase::LteDownlinkPowerControlSpectrumValueTestCase (std::string name,
+                                                                                            uint16_t earfcn, uint8_t bw, double powerTx,
+                                                                                            std::map<int, double> powerTxMap, std::vector <int> activeRbs,
+                                                                                            SpectrumValue& expected)
+  : TestCase ("Downlink Power Control: " + name),
+    m_actual (LteSpectrumValueHelper::CreateTxPowerSpectralDensity (earfcn, bw, powerTx, powerTxMap, activeRbs)),
+    m_expected (Create<SpectrumValue> (expected))
+{
+  NS_LOG_INFO ("Creating LteDownlinkPowerControlTestCase");
+}
+
+LteDownlinkPowerControlSpectrumValueTestCase::~LteDownlinkPowerControlSpectrumValueTestCase ()
+{
+}
+
+void
+LteDownlinkPowerControlSpectrumValueTestCase::DoRun (void)
+{
+  NS_LOG_INFO ("Creating LteDownlinkPowerControlSpectrumValueTestCase");
+  NS_TEST_ASSERT_MSG_EQ (m_actual->GetSpectrumModelUid (), m_expected->GetSpectrumModelUid (), "SpectrumModel UID mismatch");
+  NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL ((*m_actual), (*m_expected), 0.0000001, "SpectrumValues not equal");
+
+}
+
+LteDownlinkPowerControlTestCase::LteDownlinkPowerControlTestCase (bool changePower, uint8_t pa, std::string name)
+  : TestCase ("Downlink Power Control: " + name)
+{
+  m_changePdschConfigDedicated = changePower;
+  m_pdschConfigDedicated.pa = pa;
+  m_expectedPowerDiff = LteRrcSap::ConvertPdschConfigDedicated2Double (m_pdschConfigDedicated);
+  NS_LOG_INFO ("Creating LteDownlinkPowerControlTestCase");
+}
+
+LteDownlinkPowerControlTestCase::~LteDownlinkPowerControlTestCase ()
+{
+}
+
+void
+LteDownlinkPowerControlTestCase::DoRun (void)
+{
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
+
+  /**
+    * Simulation Topology
+    */
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFfrSimple");
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes;
+  enbNodes.Create (1);
+  ueNodes.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes );
+
+  // Install Mobility Model
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (allNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+  PointerValue tmp;
+  enbDevs.Get (0)->GetAttribute ("LteFfrAlgorithm", tmp);
+  Ptr<LteFfrSimple> simpleFfrAlgorithm = DynamicCast<LteFfrSimple>(tmp.GetObject ());
+  simpleFfrAlgorithm->ChangePdschConfigDedicated (m_changePdschConfigDedicated);
+  simpleFfrAlgorithm->SetPdschConfigDedicated (m_pdschConfigDedicated);
+
+  // Activate the default EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+
+  // Use testing chunk processor in the PHY layer
+  // It will be used to calculate data and ctrl power in downlink
+
+  Ptr<LtePhy> ue1Phy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+
+  Ptr<LteTestSinrChunkProcessor> testDlDataPowerReceived = Create<LteTestSinrChunkProcessor> ();
+  ue1Phy->GetDownlinkSpectrumPhy ()->AddDataPowerChunkProcessor (testDlDataPowerReceived);
+
+  Ptr<LteTestSinrChunkProcessor> testDlCtrlPowerReceived = Create<LteTestSinrChunkProcessor> ();
+  ue1Phy->GetDownlinkSpectrumPhy ()->AddRsPowerChunkProcessor (testDlCtrlPowerReceived);
+
+  Simulator::Stop (Seconds (0.400));
+  Simulator::Run ();
+
+  double dataPower = 10.0 * std::log10 (testDlDataPowerReceived->GetSinr ()->operator[] (0));
+  double ctrlPower = 10.0 * std::log10 (testDlCtrlPowerReceived->GetSinr ()->operator[] (0));
+  double powerDiff = (-1.0)*ctrlPower + dataPower;
+
+  NS_LOG_DEBUG ("DataPower: " << dataPower);
+  NS_LOG_DEBUG ("CtrlPower: " << ctrlPower);
+  NS_LOG_DEBUG ("PowerDifference: " << powerDiff);
+  NS_LOG_DEBUG ("ExpectedPowerDifference: " << m_expectedPowerDiff);
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (powerDiff, m_expectedPowerDiff, 0.001,
+                             "Downlink Data and Ctrl Power Difference are not equal within tolerance");
+
+  Simulator::Destroy ();
+}
+
+void
+NotifyConnectionReconfigurationUe (LteDownlinkPowerControlRrcConnectionReconfigurationTestCase *testcase,
+                                   std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
+{
+  testcase->ConnectionReconfigurationUe (context, imsi, cellId, rnti);
+}
+
+void
+NotifyConnectionReconfigurationEnb (LteDownlinkPowerControlRrcConnectionReconfigurationTestCase *testcase,
+                                    std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
+{
+  testcase->ConnectionReconfigurationEnb (context, imsi, cellId, rnti);
+}
+
+void
+ChangePdschConfigDedicatedCallback (LteDownlinkPowerControlRrcConnectionReconfigurationTestCase *testcase,
+                                    std::string context, uint16_t rnti, uint8_t pa)
+{
+  testcase->ChangePdschConfigDedicated (rnti, pa);
+}
+
+
+LteDownlinkPowerControlRrcConnectionReconfigurationTestCase::LteDownlinkPowerControlRrcConnectionReconfigurationTestCase (bool useIdealRrc, std::string name)
+  : TestCase ("Downlink Power Control: " + name),
+    m_useIdealRrc (useIdealRrc),
+    m_changePdschConfigDedicatedTriggered (false),
+    m_connectionReconfigurationUeReceived (false),
+    m_connectionReconfigurationEnbCompleted (false)
+{
+
+}
+
+LteDownlinkPowerControlRrcConnectionReconfigurationTestCase::~LteDownlinkPowerControlRrcConnectionReconfigurationTestCase ()
+{
+}
+
+void
+LteDownlinkPowerControlRrcConnectionReconfigurationTestCase::ConnectionReconfigurationEnb (std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
+{
+  if (Simulator::Now () > MilliSeconds (100))
+    {
+      NS_LOG_DEBUG ("eNb ConnectionReconfigurationCompleted");
+      m_connectionReconfigurationEnbCompleted = true;
+    }
+}
+
+void
+LteDownlinkPowerControlRrcConnectionReconfigurationTestCase::ConnectionReconfigurationUe (std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti)
+{
+  if (Simulator::Now () > MilliSeconds (100))
+    {
+      NS_LOG_DEBUG ("Ue ConnectionReconfiguration");
+      m_connectionReconfigurationUeReceived = true;
+    }
+}
+
+void
+LteDownlinkPowerControlRrcConnectionReconfigurationTestCase::ChangePdschConfigDedicated (uint16_t rnti, uint8_t pa)
+{
+  NS_LOG_DEBUG ("FFR Algorithm ChangePdschConfigDedicated");
+  m_changePdschConfigDedicatedTriggered = true;
+}
+
+void
+LteDownlinkPowerControlRrcConnectionReconfigurationTestCase::DoRun (void)
+{
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (m_useIdealRrc));
+
+  /**
+  * Simulation Topology
+  */
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFfrSimple");
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes;
+  enbNodes.Create (1);
+  ueNodes.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes );
+
+  // Install Mobility Model
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (allNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+  PointerValue tmp;
+  enbDevs.Get (0)->GetAttribute ("LteFfrAlgorithm", tmp);
+  Ptr<LteFfrSimple> simpleFfrAlgorithm = DynamicCast<LteFfrSimple>(tmp.GetObject ());
+  LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
+  pdschConfigDedicated.pa = LteRrcSap::PdschConfigDedicated::dB_6;
+  simpleFfrAlgorithm->ChangePdschConfigDedicated (true);
+  simpleFfrAlgorithm->SetPdschConfigDedicated (pdschConfigDedicated);
+
+  // Activate the default EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+
+  Config::Connect ("/NodeList/0/DeviceList/0/LteFfrAlgorithm/ChangePdschConfigDedicated",
+                   MakeBoundCallback (&ChangePdschConfigDedicatedCallback, this));
+  Config::Connect ("/NodeList/1/DeviceList/0/LteUeRrc/ConnectionReconfiguration",
+                   MakeBoundCallback (&NotifyConnectionReconfigurationUe, this));
+  Config::Connect ("/NodeList/0/DeviceList/0/LteEnbRrc/ConnectionReconfiguration",
+                   MakeBoundCallback (&NotifyConnectionReconfigurationEnb, this));
+
+  Simulator::Stop (Seconds (0.400));
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_changePdschConfigDedicatedTriggered, true,
+                         "Ffr have not changed PdschConfigDedicated for UE");
+  NS_TEST_ASSERT_MSG_EQ (m_connectionReconfigurationUeReceived, true,
+                         "Ue have not received RrcConnectionReconfiguration");
+  NS_TEST_ASSERT_MSG_EQ (m_connectionReconfigurationEnbCompleted, true,
+                         "Enb have not received RrcConnectionReconfigurationCompleted");
+
+  Simulator::Destroy ();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-downlink-power-control.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,97 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_TEST_DOWNLINK_POWER_CONTROL_H
+#define LTE_TEST_DOWNLINK_POWER_CONTROL_H
+
+#include "ns3/spectrum-value.h"
+#include <ns3/lte-rrc-sap.h>
+
+#include "ns3/spectrum-test.h"
+#include "ns3/lte-spectrum-value-helper.h"
+
+#include "ns3/test.h"
+
+using namespace ns3;
+
+/**
+ * Test 1.1 SINR calculation in downlink
+ */
+class LteDownlinkPowerControlTestSuite : public TestSuite
+{
+public:
+  LteDownlinkPowerControlTestSuite ();
+
+  double CalculateRbTxPower (double txPower, uint8_t pa);
+};
+
+class LteDownlinkPowerControlSpectrumValueTestCase : public TestCase
+{
+public:
+  LteDownlinkPowerControlSpectrumValueTestCase (std::string name,
+                                                uint16_t earfcn, uint8_t bw, double powerTx,
+                                                std::map<int, double> powerTxMap, std::vector <int> activeRbs,
+                                                SpectrumValue& expected);
+  virtual ~LteDownlinkPowerControlSpectrumValueTestCase ();
+
+private:
+  virtual void DoRun (void);
+  Ptr<SpectrumValue> m_actual;
+  Ptr<SpectrumValue> m_expected;
+
+};
+
+class LteDownlinkPowerControlTestCase : public TestCase
+{
+public:
+  LteDownlinkPowerControlTestCase (bool changePower, uint8_t pa, std::string name);
+  virtual ~LteDownlinkPowerControlTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+  bool m_changePdschConfigDedicated;
+  LteRrcSap::PdschConfigDedicated m_pdschConfigDedicated;
+  double m_expectedPowerDiff;
+};
+
+
+class LteDownlinkPowerControlRrcConnectionReconfigurationTestCase : public TestCase
+{
+public:
+  LteDownlinkPowerControlRrcConnectionReconfigurationTestCase (bool useIdealRrc, std::string name);
+  virtual ~LteDownlinkPowerControlRrcConnectionReconfigurationTestCase ();
+
+  void ConnectionReconfigurationEnb (std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti);
+
+  void ConnectionReconfigurationUe (std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti);
+
+  void ChangePdschConfigDedicated (uint16_t rnti, uint8_t pa);
+private:
+  virtual void DoRun (void);
+  bool m_useIdealRrc;
+
+  bool m_changePdschConfigDedicatedTriggered;
+  bool m_connectionReconfigurationUeReceived;
+  bool m_connectionReconfigurationEnbCompleted;
+};
+
+#endif /* LTE_TEST_DOWNLINK_POWER_CONTROL_H */
--- a/src/lte/test/lte-test-downlink-sinr.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-downlink-sinr.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -135,7 +135,7 @@
   dlPhy->SetCellId (cellId);
   ulPhy->SetCellId (cellId);
 
-  Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
+  Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> ();
   dlPhy->AddDataSinrChunkProcessor (chunkProcessor);
 
   /**
@@ -261,7 +261,7 @@
   Simulator::Run ();
 
   /**
-   * Check that the values passed to LteSinrChunkProcessor::EvaluateSinrChunk () correspond
+   * Check that the values passed to LteChunkProcessor::EvaluateChunk () correspond
    * to known values which have been calculated offline (with octave) for the generated signals
    */
   Ptr<SpectrumValue> calculatedSinr = chunkProcessor->GetSinr ();
@@ -307,7 +307,7 @@
   dlPhy->SetCellId (cellId);
   ulPhy->SetCellId (cellId);
   
-  Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
+  Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> ();
   dlPhy->AddCtrlSinrChunkProcessor (chunkProcessor);
   
   /**
@@ -433,7 +433,7 @@
   Simulator::Run ();
   
   /**
-  * Check that the values passed to LteSinrChunkProcessor::EvaluateSinrChunk () correspond
+  * Check that the values passed to LteChunkProcessor::EvaluateChunk () correspond
   * to known values which have been calculated offline (with octave) for the generated signals
   */
   Ptr<SpectrumValue> calculatedSinr = chunkProcessor->GetSinr ();
--- a/src/lte/test/lte-test-fading.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-fading.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -26,7 +26,7 @@
 
 #include "ns3/lte-phy-tag.h"
 #include "ns3/lte-test-ue-phy.h"
-#include "ns3/lte-sinr-chunk-processor.h"
+#include "ns3/lte-chunk-processor.h"
 
 #include "ns3/lte-test-fading.h"
 #include <ns3/buildings-propagation-loss-model.h>
@@ -166,7 +166,7 @@
   // 
   //   LogComponentEnable ("LteSpectrumPhy", logLevel);
   //   LogComponentEnable ("LteInterference", logLevel);
-  //   LogComponentEnable ("LteSinrChunkProcessor", logLevel);
+  //   LogComponentEnable ("LteChunkProcessor", logLevel);
   // 
   //   LogComponentEnable ("LtePropagationLossModel", logLevel);
   //   LogComponentEnable ("LossModel", logLevel);
--- a/src/lte/test/lte-test-fdbet-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-fdbet-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -207,6 +207,9 @@
 
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
--- a/src/lte/test/lte-test-fdmt-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-fdmt-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -192,6 +192,9 @@
 
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-frequency-reuse.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,1714 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include <ns3/simulator.h>
+#include <ns3/log.h>
+#include <ns3/callback.h>
+#include <ns3/config.h>
+#include <ns3/string.h>
+#include <ns3/double.h>
+#include <ns3/enum.h>
+#include <ns3/boolean.h>
+#include <ns3/pointer.h>
+
+#include "ns3/mobility-helper.h"
+#include "ns3/lte-helper.h"
+#include "ns3/point-to-point-epc-helper.h"
+#include "ns3/internet-module.h"
+#include "ns3/point-to-point-module.h"
+#include "ns3/applications-module.h"
+
+#include <ns3/ff-mac-scheduler.h>
+#include <ns3/lte-enb-net-device.h>
+#include <ns3/lte-enb-phy.h>
+#include <ns3/lte-enb-rrc.h>
+#include <ns3/lte-ue-net-device.h>
+#include <ns3/lte-ue-phy.h>
+#include <ns3/lte-ue-rrc.h>
+
+#include "lte-ffr-simple.h"
+#include "lte-simple-spectrum-phy.h"
+#include "lte-test-sinr-chunk-processor.h"
+#include <ns3/lte-common.h>
+
+#include "lte-test-frequency-reuse.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("LteFrequencyReuseTest");
+
+using namespace ns3;
+
+/**
+ * TestSuite
+ */
+
+LteFrequencyReuseTestSuite::LteFrequencyReuseTestSuite ()
+  : TestSuite ("lte-frequency-reuse", SYSTEM)
+{
+//  LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_DEBUG);
+//  LogComponentEnable ("LteFrequencyReuseTest", logLevel);
+
+  std::vector<bool> availableDlRb;
+  std::vector<bool> availableUlRb;
+  for (uint32_t i = 0; i < 12; i++)
+    {
+      availableDlRb.push_back (true);
+      availableUlRb.push_back (true);
+    }
+  for (uint32_t i = 12; i < 25; i++)
+    {
+      availableDlRb.push_back (false);
+      availableUlRb.push_back (false);
+    }
+
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrPf1", 1, "ns3::PfFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrPf2", 5, "ns3::PfFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrPss1", 1, "ns3::PssFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrPss2", 5, "ns3::PssFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrCqa1", 1, "ns3::CqaFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrCqa2", 5, "ns3::CqaFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrFdTbfq1", 1, "ns3::FdTbfqFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrFdTbfq2", 5, "ns3::FdTbfqFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrTdTbfq1", 1, "ns3::TdTbfqFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteHardFrTestCase ("DownlinkHardFrTdTbfq2", 5, "ns3::TdTbfqFfMacScheduler", 25, 25, 0, 12, 0, 12, availableDlRb, availableUlRb), TestCase::QUICK);
+
+  availableDlRb.clear ();
+  availableUlRb.clear ();
+  for (uint32_t i = 0; i < 6; i++)
+    {
+      availableDlRb.push_back (true);
+      availableUlRb.push_back (true);
+    }
+  for (uint32_t i = 6; i < 12; i++)
+    {
+      availableDlRb.push_back (false);
+      availableUlRb.push_back (false);
+    }
+  for (uint32_t i = 12; i < 18; i++)
+    {
+      availableDlRb.push_back (true);
+      availableUlRb.push_back (true);
+    }
+  for (uint32_t i = 18; i < 25; i++)
+    {
+      availableDlRb.push_back (false);
+      availableUlRb.push_back (false);
+    }
+
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrPf1", 1, "ns3::PfFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrPf2", 5, "ns3::PfFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrPss1", 1, "ns3::PssFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrPss2", 5, "ns3::PssFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrCqa1", 1, "ns3::CqaFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrCqa2", 5, "ns3::CqaFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrCqaFdTbfq1", 1, "ns3::FdTbfqFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrCqaFdTbfq2", 5, "ns3::FdTbfqFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrCqaTdTbfq1", 1, "ns3::TdTbfqFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+  AddTestCase (new LteStrictFrTestCase ("DownlinkStrictFrCqaTdTbfq2", 5, "ns3::TdTbfqFfMacScheduler", 25, 25, 6, 6, 6, 6, 6, 6, availableDlRb, availableUlRb), TestCase::QUICK);
+
+  AddTestCase (new LteStrictFrAreaTestCase ("LteStrictFrAreaTestCasePf1", "ns3::PfFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteStrictFrAreaTestCase ("LteStrictFrAreaTestCasePss1", "ns3::PssFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteStrictFrAreaTestCase ("LteStrictFrAreaTestCaseCqa1", "ns3::CqaFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteStrictFrAreaTestCase ("LteStrictFrAreaTestCaseFdTbfq1", "ns3::FdTbfqFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteStrictFrAreaTestCase ("LteStrictFrAreaTestCaseTdTbfq1", "ns3::TdTbfqFfMacScheduler"), TestCase::QUICK);
+
+  AddTestCase (new LteSoftFrAreaTestCase ("LteSoftFrAreaTestCasePf1", "ns3::PfFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteSoftFrAreaTestCase ("LteSoftFrAreaTestCasePss1", "ns3::PssFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteSoftFrAreaTestCase ("LteSoftFrAreaTestCaseCqa1", "ns3::CqaFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteSoftFrAreaTestCase ("LteSoftFrAreaTestCaseFdTbfq1", "ns3::FdTbfqFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteSoftFrAreaTestCase ("LteSoftFrAreaTestCaseTdTbfq1", "ns3::TdTbfqFfMacScheduler"), TestCase::QUICK);
+
+  AddTestCase (new LteSoftFfrAreaTestCase ("LteSoftFfrAreaTestCasePf1", "ns3::PfFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteSoftFfrAreaTestCase ("LteSoftFfrAreaTestCasePss1", "ns3::PssFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteSoftFfrAreaTestCase ("LteSoftFfrAreaTestCaseCqa1", "ns3::CqaFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteSoftFfrAreaTestCase ("LteSoftFfrAreaTestCaseFdTbfq1", "ns3::FdTbfqFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteSoftFfrAreaTestCase ("LteSoftFfrAreaTestCaseTdTbfq1", "ns3::TdTbfqFfMacScheduler"), TestCase::QUICK);
+
+  AddTestCase (new LteEnhancedFfrAreaTestCase ("LteEnhancedFfrAreaTestCasePf1", "ns3::PfFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteEnhancedFfrAreaTestCase ("LteEnhancedFfrAreaTestCasePss1", "ns3::PssFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteEnhancedFfrAreaTestCase ("LteEnhancedFfrAreaTestCaseCqa1", "ns3::CqaFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteEnhancedFfrAreaTestCase ("LteEnhancedFfrAreaTestCaseFdTbfq1", "ns3::FdTbfqFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteEnhancedFfrAreaTestCase ("LteEnhancedFfrAreaTestCaseTdTbfq1", "ns3::TdTbfqFfMacScheduler"), TestCase::QUICK);
+
+  AddTestCase (new LteDistributedFfrAreaTestCase ("LteDistributedFfrAreaTestCasePf1", "ns3::PfFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteDistributedFfrAreaTestCase ("LteDistributedFfrAreaTestCasePss1", "ns3::PssFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteDistributedFfrAreaTestCase ("LteDistributedFfrAreaTestCaseCqa1", "ns3::CqaFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteDistributedFfrAreaTestCase ("LteDistributedFfrAreaTestCaseFdTbfq1", "ns3::FdTbfqFfMacScheduler"), TestCase::QUICK);
+  AddTestCase (new LteDistributedFfrAreaTestCase ("LteDistributedFfrAreaTestCaseTdTbfq1", "ns3::TdTbfqFfMacScheduler"), TestCase::QUICK);
+}
+
+static LteFrequencyReuseTestSuite lteFrequencyReuseTestSuite;
+
+
+/**
+ * TestCase Data
+ */
+void
+DlDataRxStartNofitication (LteFrTestCase *testcase,
+                           Ptr<const SpectrumValue> spectrumValue)
+{
+  testcase->DlDataRxStart (spectrumValue);
+}
+
+void
+UlDataRxStartNofitication (LteFrTestCase *testcase,
+                           Ptr<const SpectrumValue> spectrumValue)
+{
+  testcase->UlDataRxStart (spectrumValue);
+}
+
+LteFrTestCase::LteFrTestCase (std::string name,
+                              uint32_t userNum,uint8_t dlBandwidth,uint8_t ulBandwidth,
+                              std::vector<bool> availableDlRb, std::vector<bool> availableUlRb)
+  : TestCase ("Test: " + name),
+    m_userNum (userNum),
+    m_dlBandwidth (dlBandwidth),
+    m_ulBandwidth (ulBandwidth),
+    m_availableDlRb (availableDlRb),
+    m_usedMutedDlRbg (false),
+    m_availableUlRb (availableUlRb),
+    m_usedMutedUlRbg (false)
+{
+}
+
+LteFrTestCase::~LteFrTestCase ()
+{
+}
+
+
+
+void
+LteFrTestCase::DlDataRxStart (Ptr<const SpectrumValue> spectrumValue)
+{
+  NS_LOG_DEBUG ("DL DATA Power allocation :");
+  Values::const_iterator it;
+  uint32_t i = 0;
+  for (it = spectrumValue->ConstValuesBegin (); it != spectrumValue->ConstValuesEnd (); it++)
+    {
+      double power =  (*it) * (m_dlBandwidth * 180000);
+      NS_LOG_DEBUG ("RB " << i << " POWER: " << " " << power << " isAvailable: " << m_availableDlRb[i]);
+
+      if (m_availableDlRb[i] == false && power > 0)
+        {
+          m_usedMutedDlRbg = true;
+        }
+      i++;
+    }
+}
+
+void
+LteFrTestCase::UlDataRxStart (Ptr<const SpectrumValue> spectrumValue)
+{
+  NS_LOG_DEBUG ("UL DATA Power allocation :");
+  Values::const_iterator it;
+  uint32_t i = 0;
+  for (it = spectrumValue->ConstValuesBegin (); it != spectrumValue->ConstValuesEnd (); it++)
+    {
+      double power =  (*it) * (m_ulBandwidth * 180000);
+      NS_LOG_DEBUG ("RB " << i << " POWER: " << " " << power << " isAvailable: " << m_availableUlRb[i]);
+
+      if (m_availableUlRb[i] == false && power > 0)
+        {
+          m_usedMutedUlRbg = true;
+        }
+      i++;
+    }
+}
+
+
+void
+LteFrTestCase::DoRun (void)
+{
+
+}
+
+
+LteHardFrTestCase::LteHardFrTestCase (std::string name, uint32_t userNum,
+                                      std::string schedulerType,
+                                      uint8_t dlBandwidth, uint8_t ulBandwidth,
+                                      uint8_t dlSubBandOffset, uint8_t dlSubBandwidth,
+                                      uint8_t ulSubBandOffset, uint8_t ulSubBandwidth,
+                                      std::vector<bool> availableDlRb, std::vector<bool> availableUlRb)
+  : LteFrTestCase (name, userNum, dlBandwidth, ulBandwidth, availableDlRb, availableUlRb),
+    m_schedulerType (schedulerType),
+    m_dlSubBandOffset (dlSubBandOffset),
+    m_dlSubBandwidth (dlSubBandwidth),
+    m_ulSubBandOffset (ulSubBandOffset),
+    m_ulSubBandwidth (ulSubBandwidth)
+{
+  NS_LOG_INFO ("Creating LteDownlinkFrTestCase");
+}
+
+LteHardFrTestCase::~LteHardFrTestCase ()
+{
+}
+
+void
+LteHardFrTestCase::DoRun (void)
+{
+  NS_LOG_DEBUG ("LteFrTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
+
+  /**
+    * Simulation Topology
+    */
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrHardAlgorithm");
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandOffset", UintegerValue (m_dlSubBandOffset));
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandwidth", UintegerValue (m_dlSubBandwidth));
+
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandOffset", UintegerValue (m_ulSubBandOffset));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandwidth", UintegerValue (m_ulSubBandwidth));
+
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes;
+  enbNodes.Create (1);
+  ueNodes.Create (m_userNum);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes );
+
+  // Install Mobility Model
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (allNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  lteHelper->SetSchedulerType (m_schedulerType);
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+  // Activate the default EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+
+  //Test SpectrumPhy to get signals form DL channel
+  Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testDlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  Ptr<LteEnbNetDevice> eNbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
+  testDlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetDlEarfcn (), m_dlBandwidth));
+  dlChannel->AddRx (testDlSpectrumPhy);
+
+  testDlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&DlDataRxStartNofitication, this));
+
+  //Test SpectrumPhy to get signals form UL channel
+  Ptr<LteSpectrumPhy> ueUlSpectrumPhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetUplinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> ulChannel = ueUlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testUlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  testUlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetUlEarfcn (), m_ulBandwidth));
+  ulChannel->AddRx (testUlSpectrumPhy);
+
+  testUlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&UlDataRxStartNofitication, this));
+
+  Simulator::Stop (Seconds (0.500));
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedMutedDlRbg, false,
+                         "Scheduler used DL RBG muted by FFR Algorithm");
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedMutedUlRbg, false,
+                         "Scheduler used UL RBG muted by FFR Algorithm");
+
+  Simulator::Destroy ();
+}
+
+
+
+LteStrictFrTestCase::LteStrictFrTestCase (std::string name, uint32_t userNum,
+                                          std::string schedulerType,
+                                          uint8_t dlBandwidth, uint8_t ulBandwidth,
+                                          uint8_t dlCommonSubBandwidth, uint8_t dlEdgeSubBandOffset, uint8_t dlEdgeSubBandwidth,
+                                          uint8_t ulCommonSubBandwidth, uint8_t ulEdgeSubBandOffset, uint8_t ulEdgeSubBandwidth,
+                                          std::vector<bool> availableDlRb, std::vector<bool> availableUlRb)
+  : LteFrTestCase (name, userNum, dlBandwidth, ulBandwidth, availableDlRb, availableUlRb),
+    m_schedulerType (schedulerType),
+    m_dlCommonSubBandwidth (dlCommonSubBandwidth),
+    m_dlEdgeSubBandOffset (dlEdgeSubBandOffset),
+    m_dlEdgeSubBandwidth (dlEdgeSubBandwidth),
+    m_ulCommonSubBandwidth (ulCommonSubBandwidth),
+    m_ulEdgeSubBandOffset (ulEdgeSubBandOffset),
+    m_ulEdgeSubBandwidth (ulEdgeSubBandwidth)
+{
+  NS_LOG_INFO ("Creating LteFrTestCase");
+}
+
+LteStrictFrTestCase::~LteStrictFrTestCase ()
+{
+}
+
+void
+LteStrictFrTestCase::DoRun (void)
+{
+  NS_LOG_DEBUG ("LteFrTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
+
+  /**
+    * Simulation Topology
+    */
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrStrictAlgorithm");
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlCommonSubBandwidth", UintegerValue (m_dlCommonSubBandwidth));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (m_dlEdgeSubBandOffset));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (m_dlEdgeSubBandwidth));
+
+  lteHelper->SetFfrAlgorithmAttribute ("UlCommonSubBandwidth", UintegerValue (m_ulCommonSubBandwidth));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandOffset", UintegerValue (m_ulEdgeSubBandOffset));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandwidth", UintegerValue (m_ulEdgeSubBandwidth));
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes;
+  enbNodes.Create (1);
+  ueNodes.Create (m_userNum);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes );
+
+  // Install Mobility Model
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (allNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  lteHelper->SetSchedulerType (m_schedulerType);
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+  // Activate the default EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+
+  //Test SpectrumPhy to get signals form DL channel
+  Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testDlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  Ptr<LteEnbNetDevice> eNbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
+  testDlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetDlEarfcn (), m_dlBandwidth));
+  dlChannel->AddRx (testDlSpectrumPhy);
+
+  testDlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&DlDataRxStartNofitication, this));
+
+  //Test SpectrumPhy to get signals form UL channel
+  Ptr<LteSpectrumPhy> ueUlSpectrumPhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetUplinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> ulChannel = ueUlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testUlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  testUlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetUlEarfcn (), m_ulBandwidth));
+  ulChannel->AddRx (testUlSpectrumPhy);
+
+  testUlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&UlDataRxStartNofitication, this));
+
+  Simulator::Stop (Seconds (0.500));
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedMutedDlRbg, false,
+                         "Scheduler used DL RBG muted by FFR Algorithm");
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedMutedUlRbg, false,
+                         "Scheduler used UL RBG muted by FFR Algorithm");
+
+  Simulator::Destroy ();
+}
+
+void
+DlDataRxStartNofiticationArea (LteFrAreaTestCase *testcase,
+                               Ptr<const SpectrumValue> spectrumValue)
+{
+  testcase->DlDataRxStart (spectrumValue);
+}
+
+void
+UlDataRxStartNofiticationArea (LteFrAreaTestCase *testcase,
+                               Ptr<const SpectrumValue> spectrumValue)
+{
+  testcase->UlDataRxStart (spectrumValue);
+}
+
+LteFrAreaTestCase::LteFrAreaTestCase (std::string name, std::string schedulerType)
+  : TestCase ("Test: " + name),
+    m_schedulerType (schedulerType)
+{
+  m_dlBandwidth = 25;
+  m_ulBandwidth = 25;
+  m_usedWrongDlRbg = false;
+  m_usedWrongUlRbg = false;
+}
+LteFrAreaTestCase::~LteFrAreaTestCase ()
+{
+}
+
+void
+LteFrAreaTestCase::DlDataRxStart (Ptr<const SpectrumValue> spectrumValue)
+{
+  //need time to report new UE measurements, and wait because of filtering
+  if ( (Simulator::Now () - m_teleportTime ) < MilliSeconds (400))
+    {
+      return;
+    }
+
+  NS_LOG_DEBUG ("DL DATA Power allocation :");
+  Values::const_iterator it;
+  uint32_t i = 0;
+  for (it = spectrumValue->ConstValuesBegin (); it != spectrumValue->ConstValuesEnd (); it++)
+    {
+      double power =  (*it) * (m_dlBandwidth * 180000);
+      NS_LOG_DEBUG ("RB " << i << " POWER: " << " " << power);
+      NS_LOG_DEBUG ("RB " << i << " POWER: " << " " << power
+                          << " Available: " << m_expectedDlRb[i] << " Expected Power: " << m_expectedDlPower );
+
+      if (m_expectedDlRb[i] == false && power > 0)
+        {
+          m_usedWrongDlRbg = true;
+        }
+      else if (m_expectedDlRb[i] == true && power > 0)
+        {
+          NS_TEST_ASSERT_MSG_EQ_TOL (power, m_expectedDlPower, 0.1,
+                                     "Wrong Data Channel DL Power level");
+        }
+      i++;
+    }
+}
+
+void
+LteFrAreaTestCase::UlDataRxStart (Ptr<const SpectrumValue> spectrumValue)
+{
+  //need time to report new UE measurements, and wait because of filtering
+  if ( (Simulator::Now () - m_teleportTime ) < MilliSeconds (400))
+    {
+      return;
+    }
+
+  NS_LOG_DEBUG ("UL DATA Power allocation :");
+  Values::const_iterator it;
+  uint32_t i = 0;
+  for (it = spectrumValue->ConstValuesBegin (); it != spectrumValue->ConstValuesEnd (); it++)
+    {
+      double power =  (*it) * (m_ulBandwidth * 180000);
+      NS_LOG_DEBUG ("RB " << i << " POWER: " << power << " expectedUlPower: " << m_expectedUlPower);
+      if (m_expectedUlRb[i] == false && power > 0)
+        {
+          m_usedWrongUlRbg = true;
+        }
+      else if (m_expectedUlRb[i] == true && power > 0)
+        {
+          NS_TEST_ASSERT_MSG_EQ_TOL (power, m_expectedUlPower, 0.01,
+                                     "Wrong Data Channel UL Power level" << Simulator::Now ().GetSeconds ());
+        }
+      i++;
+    }
+}
+
+void
+LteFrAreaTestCase::SimpleTeleportUe (uint32_t x, uint32_t y)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("Teleport UE to : (" << x << ", " << y << ", 0)");
+  m_teleportTime = Simulator::Now ();
+  m_ueMobility->SetPosition (Vector (x, y, 0.0));
+}
+
+void
+LteFrAreaTestCase::TeleportUe (uint32_t x, uint32_t y, double expectedPower,
+                               std::vector<bool> expectedDlRb)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("Teleport UE to : (" << x << ", " << y << ", 0)");
+  m_teleportTime = Simulator::Now ();
+  m_ueMobility->SetPosition (Vector (x, y, 0.0));
+  m_expectedDlPower = expectedPower;
+  m_expectedDlRb = expectedDlRb;
+}
+
+void
+LteFrAreaTestCase::TeleportUe2 (Ptr<Node> ueNode, uint32_t x, uint32_t y, double expectedPower,
+                                std::vector<bool> expectedDlRb)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("Teleport UE to : (" << x << ", " << y << ", 0)");
+
+  Ptr<MobilityModel> ueMobility = ueNode->GetObject<MobilityModel> ();
+  ueMobility->SetPosition (Vector (x, y, 0.0));
+  m_teleportTime = Simulator::Now ();
+  m_expectedDlPower = expectedPower;
+  m_expectedDlRb = expectedDlRb;
+}
+
+void
+LteFrAreaTestCase::SetDlExpectedValues (double expectedDlPower, std::vector<bool> expectedDlRb)
+{
+  NS_LOG_FUNCTION (this);
+  m_expectedDlPower = expectedDlPower;
+  m_expectedDlRb = expectedDlRb;
+}
+
+void
+LteFrAreaTestCase::SetUlExpectedValues (double expectedUlPower, std::vector<bool> expectedUlRb)
+{
+  NS_LOG_FUNCTION (this);
+  m_expectedUlPower = expectedUlPower;
+  m_expectedUlRb = expectedUlRb;
+}
+
+void
+LteFrAreaTestCase::DoRun (void)
+{
+}
+
+LteStrictFrAreaTestCase::LteStrictFrAreaTestCase (std::string name, std::string schedulerType)
+  : LteFrAreaTestCase (name, schedulerType)
+{
+  NS_LOG_INFO ("Creating LteFrTestCase");
+}
+
+LteStrictFrAreaTestCase::~LteStrictFrAreaTestCase ()
+{
+}
+
+void
+LteStrictFrAreaTestCase::DoRun (void)
+{
+  NS_LOG_DEBUG ("LteStrictFrAreaTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes1;
+  NodeContainer ueNodes2;
+  enbNodes.Create (2);
+  ueNodes1.Create (1);
+  ueNodes2.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2);
+
+  /*
+   * The topology is the following:
+   *
+   *  eNB1            UE1                                      eNB2
+   *    |              |                                         |
+   *    x ------------ x ------------------------ x ------------ x----UE2
+   *         200 m               600 m                  200 m      20 m
+   *
+   */
+
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));   // eNB1
+  positionAlloc->Add (Vector (1000, 0.0, 0.0)); // eNB2
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));  // UE1
+  positionAlloc->Add (Vector (1020, 0.0, 0.0));  // UE2
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+  m_ueMobility = ueNodes1.Get (0)->GetObject<MobilityModel> ();
+
+  // Disable layer-3 filtering
+  Config::SetDefault ("ns3::LteEnbRrc::RsrpFilterCoefficient",
+                      UintegerValue (0));
+  Config::SetDefault ("ns3::LteEnbRrc::RsrqFilterCoefficient",
+                      UintegerValue (0));
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs1;
+  NetDeviceContainer ueDevs2;
+  lteHelper->SetSchedulerType (m_schedulerType);
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrStrictAlgorithm");
+  lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
+  lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlCommonSubBandwidth", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (6));
+
+  lteHelper->SetFfrAlgorithmAttribute ("UlCommonSubBandwidth", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandOffset", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandwidth", UintegerValue (6));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrNoOpAlgorithm");
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
+
+  ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
+  ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs1, enbDevs.Get (0));
+  lteHelper->Attach (ueDevs2, enbDevs.Get (1));
+
+  // Activate an EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs1, bearer);
+  lteHelper->ActivateDataRadioBearer (ueDevs2, bearer);
+
+  //Test SpectrumPhy to get signals form DL channel
+  Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testDlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  Ptr<LteEnbNetDevice> eNbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
+  testDlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetDlEarfcn (), m_dlBandwidth));
+  dlChannel->AddRx (testDlSpectrumPhy);
+
+  testDlSpectrumPhy->SetCellId (1);
+
+  testDlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&DlDataRxStartNofiticationArea, this));
+
+  //Test SpectrumPhy to get signals form UL channel
+  Ptr<LteSpectrumPhy> ueUlSpectrumPhy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetUplinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> ulChannel = ueUlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testUlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  testUlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetUlEarfcn (), m_ulBandwidth));
+  ulChannel->AddRx (testUlSpectrumPhy);
+
+  testUlSpectrumPhy->SetCellId (1);
+
+  testUlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&UlDataRxStartNofiticationArea, this));
+
+  std::vector<bool> expectedDlRbCenterArea;
+  expectedDlRbCenterArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbCenterArea;
+  expectedUlRbCenterArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 0; i < 6; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+      expectedUlRbCenterArea[i] = true;
+    }
+
+  std::vector<bool> expectedDlRbEdgeArea;
+  expectedDlRbEdgeArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbEdgeArea;
+  expectedUlRbEdgeArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 12; i < 18; i++)
+    {
+      expectedDlRbEdgeArea[i] = true;
+      expectedUlRbEdgeArea[i] = true;
+    }
+
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::TeleportUe, this, 200, 0, 1, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0150543, expectedUlRbCenterArea );
+
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::TeleportUe, this, 800, 0, 2, expectedDlRbEdgeArea );
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.199526, expectedUlRbEdgeArea );
+
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::TeleportUe, this, 200, 0, 1, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0150543, expectedUlRbCenterArea );
+
+  Simulator::Stop (Seconds (1.500));
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongDlRbg, false,
+                         "Scheduler used DL RB muted by FFR Algorithm");
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongUlRbg, false,
+                         "Scheduler used UL RB muted by FFR Algorithm");
+
+  Simulator::Destroy ();
+}
+
+LteSoftFrAreaTestCase::LteSoftFrAreaTestCase (std::string name, std::string schedulerType)
+  : LteFrAreaTestCase (name, schedulerType)
+{
+  NS_LOG_INFO ("Creating LteSoftFrAreaTestCase");
+}
+
+LteSoftFrAreaTestCase::~LteSoftFrAreaTestCase ()
+{
+}
+
+void
+LteSoftFrAreaTestCase::DoRun (void)
+{
+  NS_LOG_DEBUG ("LteSoftFrAreaTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes1;
+  NodeContainer ueNodes2;
+  enbNodes.Create (2);
+  ueNodes1.Create (1);
+  ueNodes2.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2);
+
+  /*
+   * The topology is the following:
+   *
+   *  eNB1            UE1                                      eNB2
+   *    |              |                                         |
+   *    x ------------ x ------------------------ x ------------ x----UE2
+   *         200 m               600 m                  200 m      20 m
+   *
+   */
+
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));   // eNB1
+  positionAlloc->Add (Vector (1000, 0.0, 0.0)); // eNB2
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));  // UE1
+  positionAlloc->Add (Vector (1020, 0.0, 0.0));  // UE2
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+  m_ueMobility = ueNodes1.Get (0)->GetObject<MobilityModel> ();
+
+  // Disable layer-3 filtering
+  Config::SetDefault ("ns3::LteEnbRrc::RsrpFilterCoefficient",
+                      UintegerValue (0));
+  Config::SetDefault ("ns3::LteEnbRrc::RsrqFilterCoefficient",
+                      UintegerValue (0));
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs1;
+  NetDeviceContainer ueDevs2;
+  lteHelper->SetSchedulerType (m_schedulerType);
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrSoftAlgorithm");
+  lteHelper->SetFfrAlgorithmAttribute ("AllowCenterUeUseEdgeSubBand", BooleanValue (false));
+  lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
+  lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (8));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (8));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandOffset", UintegerValue (8));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandwidth", UintegerValue (8));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrNoOpAlgorithm");
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
+
+  ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
+  ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs1, enbDevs.Get (0));
+  lteHelper->Attach (ueDevs2, enbDevs.Get (1));
+
+  // Activate an EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs1, bearer);
+  lteHelper->ActivateDataRadioBearer (ueDevs2, bearer);
+
+  //Test SpectrumPhy to get signals form DL channel
+  Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testDlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  Ptr<LteEnbNetDevice> eNbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
+  testDlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetDlEarfcn (), m_dlBandwidth));
+  dlChannel->AddRx (testDlSpectrumPhy);
+
+  testDlSpectrumPhy->SetCellId (1);
+
+  testDlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&DlDataRxStartNofiticationArea, this));
+
+  //Test SpectrumPhy to get signals form UL channel
+  Ptr<LteSpectrumPhy> ueUlSpectrumPhy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetUplinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> ulChannel = ueUlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testUlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  testUlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetUlEarfcn (), m_ulBandwidth));
+  ulChannel->AddRx (testUlSpectrumPhy);
+
+  testUlSpectrumPhy->SetCellId (1);
+
+  testUlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&UlDataRxStartNofiticationArea, this));
+
+
+  std::vector<bool> expectedDlRbCenterArea;
+  expectedDlRbCenterArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbCenterArea;
+  expectedUlRbCenterArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 0; i < 8; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+      expectedUlRbCenterArea[i] = true;
+    }
+  for (uint32_t i = 16; i < 25; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+    }
+
+  std::vector<bool> expectedDlRbEdgeArea;
+  expectedDlRbEdgeArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbEdgeArea;
+  expectedUlRbEdgeArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 8; i < 16; i++)
+    {
+      expectedDlRbEdgeArea[i] = true;
+      expectedUlRbEdgeArea[i] = true;
+    }
+
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::TeleportUe, this, 200, 0, 1, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0150543, expectedUlRbCenterArea );
+
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::TeleportUe, this, 800, 0, 2, expectedDlRbEdgeArea );
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.199526, expectedUlRbEdgeArea );
+
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::TeleportUe, this, 200, 0, 1, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0150543, expectedUlRbCenterArea );
+
+  Simulator::Stop (Seconds (1.500));
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongDlRbg, false,
+                         "Scheduler used DL RBG muted by FFR Algorithm");
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongUlRbg, false,
+                         "Scheduler used UL RB muted by FFR Algorithm");
+
+  Simulator::Destroy ();
+}
+
+LteSoftFfrAreaTestCase::LteSoftFfrAreaTestCase (std::string name, std::string schedulerType)
+  : LteFrAreaTestCase (name, schedulerType)
+{
+  NS_LOG_INFO ("Creating LteSoftFfrAreaTestCase");
+}
+
+LteSoftFfrAreaTestCase::~LteSoftFfrAreaTestCase ()
+{
+}
+
+void
+LteSoftFfrAreaTestCase::DoRun (void)
+{
+  NS_LOG_DEBUG ("LteSoftFfrAreaTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes1;
+  NodeContainer ueNodes2;
+  enbNodes.Create (2);
+  ueNodes1.Create (1);
+  ueNodes2.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2);
+
+  /*
+   * The topology is the following:
+   *
+   *  eNB1            UE1                                      eNB2
+   *    |              |                                         |
+   *    x ------------ x ------------------------ x ------------ x----UE2
+   *         200 m               600 m                  200 m      20 m
+   *
+   */
+
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));   // eNB1
+  positionAlloc->Add (Vector (1000, 0.0, 0.0)); // eNB2
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));  // UE1
+  positionAlloc->Add (Vector (1020, 0.0, 0.0));  // UE2
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+  m_ueMobility = ueNodes1.Get (0)->GetObject<MobilityModel> ();
+
+  // Disable layer-3 filtering
+  Config::SetDefault ("ns3::LteEnbRrc::RsrpFilterCoefficient",
+                      UintegerValue (0));
+  Config::SetDefault ("ns3::LteEnbRrc::RsrqFilterCoefficient",
+                      UintegerValue (0));
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs1;
+  NetDeviceContainer ueDevs2;
+  lteHelper->SetSchedulerType (m_schedulerType);
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFfrSoftAlgorithm");
+  lteHelper->SetFfrAlgorithmAttribute ("CenterRsrqThreshold", UintegerValue (28));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgeRsrqThreshold", UintegerValue (18));
+  lteHelper->SetFfrAlgorithmAttribute ("CenterAreaPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB_3));
+  lteHelper->SetFfrAlgorithmAttribute ("MediumAreaPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+
+  lteHelper->SetFfrAlgorithmAttribute ("UlCommonSubBandwidth", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("DlCommonSubBandwidth", UintegerValue (6));
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandOffset", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandwidth", UintegerValue (6));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrNoOpAlgorithm");
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
+
+  ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
+  ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs1, enbDevs.Get (0));
+  lteHelper->Attach (ueDevs2, enbDevs.Get (1));
+
+  // Activate an EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs1, bearer);
+  lteHelper->ActivateDataRadioBearer (ueDevs2, bearer);
+
+  //Test SpectrumPhy to get signals form DL channel
+  Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testDlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  Ptr<LteEnbNetDevice> eNbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
+  testDlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetDlEarfcn (), m_dlBandwidth));
+  dlChannel->AddRx (testDlSpectrumPhy);
+
+  testDlSpectrumPhy->SetCellId (1);
+
+  testDlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&DlDataRxStartNofiticationArea, this));
+
+  //Test SpectrumPhy to get signals form UL channel
+  Ptr<LteSpectrumPhy> ueUlSpectrumPhy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetUplinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> ulChannel = ueUlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testUlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  testUlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetUlEarfcn (), m_ulBandwidth));
+  ulChannel->AddRx (testUlSpectrumPhy);
+
+  testUlSpectrumPhy->SetCellId (1);
+
+  testUlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&UlDataRxStartNofiticationArea, this));
+
+  double expectedDlPowerCenterArea = 0.5;
+  std::vector<bool> expectedDlRbCenterArea;
+  expectedDlRbCenterArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbCenterArea;
+  expectedUlRbCenterArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 6; i < 12; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+      expectedUlRbCenterArea[i] = true;
+    }
+  for (uint32_t i = 18; i < 25; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+      expectedUlRbCenterArea[i] = true;
+    }
+
+  double expectedDlPowerMiddleArea = 1.0;
+  std::vector<bool> expectedDlRbMiddleArea;
+  expectedDlRbMiddleArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbMiddleArea;
+  expectedUlRbMiddleArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 0; i < 6; i++)
+    {
+      expectedDlRbMiddleArea[i] = true;
+      expectedUlRbMiddleArea[i] = true;
+    }
+
+  double expectedDlPowerEdgeArea = 2.0;
+  std::vector<bool> expectedDlRbEdgeArea;
+  expectedDlRbEdgeArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbEdgeArea;
+  expectedUlRbEdgeArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 12; i < 18; i++)
+    {
+      expectedDlRbEdgeArea[i] = true;
+      expectedUlRbEdgeArea[i] = true;
+    }
+
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::TeleportUe, this, 200, 0,
+                       expectedDlPowerCenterArea, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0150543, expectedUlRbCenterArea );
+
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::TeleportUe, this, 600, 0,
+                       expectedDlPowerMiddleArea, expectedDlRbMiddleArea );
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.135489, expectedUlRbMiddleArea );
+
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::TeleportUe, this, 800, 0,
+                       expectedDlPowerEdgeArea, expectedDlRbEdgeArea );
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.199526, expectedUlRbEdgeArea );
+
+  Simulator::Schedule (MilliSeconds (1501),
+                       &LteFrAreaTestCase::TeleportUe, this, 600, 0,
+                       expectedDlPowerMiddleArea, expectedDlRbMiddleArea );
+  Simulator::Schedule (MilliSeconds (1501),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.135489, expectedUlRbMiddleArea );
+
+  Simulator::Schedule (MilliSeconds (2001),
+                       &LteFrAreaTestCase::TeleportUe, this, 200, 0,
+                       expectedDlPowerCenterArea, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (2001),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0150543, expectedUlRbCenterArea );
+
+  Simulator::Stop (Seconds (2.500));
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongDlRbg, false,
+                         "Scheduler used DL RBG muted by FFR Algorithm");
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongUlRbg, false,
+                         "Scheduler used UL RB muted by FFR Algorithm");
+
+  Simulator::Destroy ();
+}
+
+
+LteEnhancedFfrAreaTestCase::LteEnhancedFfrAreaTestCase (std::string name, std::string schedulerType)
+  : LteFrAreaTestCase (name, schedulerType)
+{
+  NS_LOG_INFO ("Creating LteEnhancedFfrAreaTestCase");
+}
+
+LteEnhancedFfrAreaTestCase::~LteEnhancedFfrAreaTestCase ()
+{
+}
+
+void
+LteEnhancedFfrAreaTestCase::DoRun (void)
+{
+  NS_LOG_DEBUG ("LteEnhancedFfrAreaTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  Config::SetDefault ("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue (true));
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes1;
+  NodeContainer ueNodes2;
+  enbNodes.Create (2);
+  ueNodes1.Create (1);
+  ueNodes2.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2);
+
+  /*
+   * The topology is the following:
+   *
+   *  eNB1            UE1                                      eNB2
+   *    |              |                                         |
+   *    x ------------ x ------------------------ x ------------ x----UE2
+   *         200 m               600 m                  200 m      20 m
+   *
+   */
+
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));   // eNB1
+  positionAlloc->Add (Vector (1000, 0.0, 0.0)); // eNB2
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));  // UE1
+  positionAlloc->Add (Vector (1020, 0.0, 0.0));  // UE2
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+  m_ueMobility = ueNodes1.Get (0)->GetObject<MobilityModel> ();
+
+  // Disable layer-3 filtering
+  Config::SetDefault ("ns3::LteEnbRrc::RsrpFilterCoefficient",
+                      UintegerValue (0));
+  Config::SetDefault ("ns3::LteEnbRrc::RsrqFilterCoefficient",
+                      UintegerValue (0));
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs1;
+  NetDeviceContainer ueDevs2;
+  lteHelper->SetSchedulerType (m_schedulerType);
+  lteHelper->SetSchedulerAttribute ("HarqEnabled",  BooleanValue (true));
+
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (m_dlBandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (m_ulBandwidth));
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFfrEnhancedAlgorithm");
+  lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
+  lteHelper->SetFfrAlgorithmAttribute ("DlCqiThreshold", UintegerValue (10));
+  lteHelper->SetFfrAlgorithmAttribute ("UlCqiThreshold", UintegerValue (15));
+  lteHelper->SetFfrAlgorithmAttribute ("CenterAreaPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("UlReuse3SubBandwidth", UintegerValue (4));
+  lteHelper->SetFfrAlgorithmAttribute ("UlReuse1SubBandwidth", UintegerValue (4));
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("DlReuse3SubBandwidth", UintegerValue (4));
+  lteHelper->SetFfrAlgorithmAttribute ("DlReuse1SubBandwidth", UintegerValue (4));
+
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrNoOpAlgorithm");
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
+
+  ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
+  ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs1, enbDevs.Get (0));
+  lteHelper->Attach (ueDevs2, enbDevs.Get (1));
+
+  // Activate an EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs1, bearer);
+  lteHelper->ActivateDataRadioBearer (ueDevs2, bearer);
+
+  //Test SpectrumPhy to get signals form DL channel
+  Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testDlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  Ptr<LteEnbNetDevice> eNbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
+  testDlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetDlEarfcn (), m_dlBandwidth));
+  dlChannel->AddRx (testDlSpectrumPhy);
+
+  testDlSpectrumPhy->SetCellId (1);
+
+  testDlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&DlDataRxStartNofiticationArea, this));
+
+  //Test SpectrumPhy to get signals form UL channel
+  Ptr<LteSpectrumPhy> ueUlSpectrumPhy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetUplinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> ulChannel = ueUlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testUlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  testUlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetUlEarfcn (), m_ulBandwidth));
+  ulChannel->AddRx (testUlSpectrumPhy);
+
+  testUlSpectrumPhy->SetCellId (1);
+
+  testUlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&UlDataRxStartNofiticationArea, this));
+
+  double expectedDlPowerCenterArea = 0.251189;
+  std::vector<bool> expectedDlRbCenterArea;
+  expectedDlRbCenterArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbCenterArea;
+  expectedUlRbCenterArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 0; i < 8; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+      expectedUlRbCenterArea[i] = true;
+    }
+  for (uint32_t i = 12; i < 16; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+      expectedUlRbCenterArea[i] = true;
+    }
+  for (uint32_t i = 20; i < 24; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+      expectedUlRbCenterArea[i] = true;
+    }
+
+  double expectedDlPowerMiddleArea = 0.251189;
+  std::vector<bool> expectedDlRbMiddleArea;
+  expectedDlRbMiddleArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbMiddleArea;
+  expectedUlRbMiddleArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 4; i < 8; i++)
+    {
+      expectedDlRbMiddleArea[i] = true;
+      expectedUlRbMiddleArea[i] = true;
+    }
+
+  double expectedDlPowerEdgeArea = 1.0;
+  std::vector<bool> expectedDlRbEdgeArea;
+  expectedDlRbEdgeArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbEdgeArea;
+  expectedUlRbEdgeArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 0; i < 4; i++)
+    {
+      expectedDlRbEdgeArea[i] = true;
+      expectedUlRbEdgeArea[i] = true;
+    }
+
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteEnhancedFfrAreaTestCase::TeleportUe, this, 100, 0,
+                       expectedDlPowerCenterArea, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.00250905, expectedUlRbCenterArea );
+
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteEnhancedFfrAreaTestCase::TeleportUe, this, 300, 0,
+                       expectedDlPowerMiddleArea, expectedDlRbMiddleArea );
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0225815, expectedUlRbMiddleArea );
+
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteEnhancedFfrAreaTestCase::TeleportUe, this, 600, 0,
+                       expectedDlPowerEdgeArea, expectedDlRbEdgeArea );
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0903259, expectedUlRbEdgeArea );
+
+  Simulator::Schedule (MilliSeconds (1501),
+                       &LteEnhancedFfrAreaTestCase::TeleportUe, this, 100, 0,
+                       expectedDlPowerCenterArea, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (1501),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.00250905, expectedUlRbCenterArea );
+
+  Simulator::Schedule (MilliSeconds (2001),
+                       &LteEnhancedFfrAreaTestCase::TeleportUe, this, 300, 0,
+                       expectedDlPowerMiddleArea, expectedDlRbMiddleArea );
+  Simulator::Schedule (MilliSeconds (2001),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0225815, expectedUlRbCenterArea );
+
+  Simulator::Stop (Seconds (2.500));
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongDlRbg, false,
+                         "Scheduler used DL RBG muted by FFR Algorithm");
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongUlRbg, false,
+                         "Scheduler used UL RB muted by FFR Algorithm");
+
+  Simulator::Destroy ();
+}
+
+
+LteDistributedFfrAreaTestCase::LteDistributedFfrAreaTestCase (std::string name, std::string schedulerType)
+  : LteFrAreaTestCase (name, schedulerType)
+{
+  NS_LOG_INFO ("Creating LteDistributedFfrAreaTestCase");
+}
+
+LteDistributedFfrAreaTestCase::~LteDistributedFfrAreaTestCase ()
+{
+}
+
+void
+LteDistributedFfrAreaTestCase::DoRun (void)
+{
+  NS_LOG_DEBUG ("LteDistributedFfrAreaTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  Config::SetDefault ("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue (true));
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+
+  // Disable layer-3 filtering
+  Config::SetDefault ("ns3::LteEnbRrc::RsrpFilterCoefficient",
+                      UintegerValue (0));
+  Config::SetDefault ("ns3::LteEnbRrc::RsrqFilterCoefficient",
+                      UintegerValue (0));
+
+  uint8_t bandwidth = 25;
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper> ();
+  lteHelper->SetEpcHelper (epcHelper);
+  lteHelper->SetHandoverAlgorithmType ("ns3::NoOpHandoverAlgorithm"); // disable automatic handover
+
+  Ptr<Node> pgw = epcHelper->GetPgwNode ();
+
+  // Create a single RemoteHost
+  NodeContainer remoteHostContainer;
+  remoteHostContainer.Create (1);
+  Ptr<Node> remoteHost = remoteHostContainer.Get (0);
+  InternetStackHelper internet;
+  internet.Install (remoteHostContainer);
+
+  // Create the Internet
+  PointToPointHelper p2ph;
+  p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
+  p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
+  p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
+  NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
+  Ipv4AddressHelper ipv4h;
+  ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
+  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
+  Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1);
+
+  // Routing of the Internet Host (towards the LTE network)
+  Ipv4StaticRoutingHelper ipv4RoutingHelper;
+  Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
+  // interface 0 is localhost, 1 is the p2p device
+  remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes1;
+  NodeContainer ueNodes2;
+  enbNodes.Create (2);
+  ueNodes1.Create (2);
+  ueNodes2.Create (1);
+  NodeContainer ueNodes = NodeContainer ( ueNodes1, ueNodes2);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2);
+
+  /*
+   * The topology is the following:
+   *
+   *  eNB1            UE1                        UE2            eNB2
+   *    |              |                          |              |
+   *    x ------------ x ------------------------ x ------------ x
+   *         200 m               600 m                  200 m
+   *
+   */
+
+  // Install Mobility Model
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));                  // eNB1
+  positionAlloc->Add (Vector (1000,  0.0, 0.0));                // eNB2
+
+  positionAlloc->Add (Vector (200, 0.0, 0.0));                  // UE1
+  positionAlloc->Add (Vector (200, 0.0, 0.0));                  // UE1
+  positionAlloc->Add (Vector (800, 0.0, 0.0));                  // UE2
+
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+  m_ueMobility = ueNodes2.Get (0)->GetObject<MobilityModel> ();
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs1;
+  NetDeviceContainer ueDevs2;
+  lteHelper->SetSchedulerType (m_schedulerType);
+
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
+
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFfrDistributedAlgorithm");
+  lteHelper->SetFfrAlgorithmAttribute ("CalculationInterval", TimeValue (MilliSeconds (10)));
+  lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
+  lteHelper->SetFfrAlgorithmAttribute ("RsrpDifferenceThreshold", UintegerValue (5));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgeRbNum", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
+
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
+  ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
+
+  NetDeviceContainer ueLteDevs;
+  ueLteDevs.Add (ueDevs1);
+  ueLteDevs.Add (ueDevs2);
+
+  // Add X2 inteface
+  lteHelper->AddX2Interface (enbNodes);
+
+  // Install the IP stack on the UEs
+  internet.Install (ueNodes);
+  Ipv4InterfaceContainer ueIpIfaces;
+  ueIpIfaces = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevs));
+  // Assign IP address to UEs, and install applications
+  for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
+    {
+      Ptr<Node> ueNode = ueNodes.Get (u);
+      // Set the default gateway for the UE
+      Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
+      ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
+    }
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs1, enbDevs.Get (0));
+  lteHelper->Attach (ueDevs2, enbDevs.Get (1));
+
+
+  // Install and start applications on UEs and remote host
+  uint16_t dlPort = 10000;
+  uint16_t ulPort = 20000;
+
+  // randomize a bit start times to avoid simulation artifacts
+  // (e.g., buffer overflows due to packet transmissions happening
+  // exactly at the same time)
+  Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable> ();
+  startTimeSeconds->SetAttribute ("Min", DoubleValue (0));
+  startTimeSeconds->SetAttribute ("Max", DoubleValue (0.010));
+
+  for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
+    {
+      Ptr<Node> ue = ueNodes.Get (u);
+      // Set the default gateway for the UE
+      Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ());
+      ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
+
+      for (uint32_t b = 0; b < 1; ++b)
+        {
+          ++dlPort;
+          ++ulPort;
+
+          ApplicationContainer clientApps;
+          ApplicationContainer serverApps;
+
+          NS_LOG_LOGIC ("installing UDP DL app for UE " << u);
+          UdpClientHelper dlClientHelper (ueIpIfaces.GetAddress (u), dlPort);
+          dlClientHelper.SetAttribute ("MaxPackets", UintegerValue (1000000));
+          dlClientHelper.SetAttribute ("Interval", TimeValue (MilliSeconds (1.0)));
+          clientApps.Add (dlClientHelper.Install (remoteHost));
+          PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory",
+                                               InetSocketAddress (Ipv4Address::GetAny (), dlPort));
+          serverApps.Add (dlPacketSinkHelper.Install (ue));
+
+          NS_LOG_LOGIC ("installing UDP UL app for UE " << u);
+          UdpClientHelper ulClientHelper (remoteHostAddr, ulPort);
+          ulClientHelper.SetAttribute ("MaxPackets", UintegerValue (1000000));
+          ulClientHelper.SetAttribute ("Interval", TimeValue (MilliSeconds (1.0)));
+          clientApps.Add (ulClientHelper.Install (ue));
+          PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory",
+                                               InetSocketAddress (Ipv4Address::GetAny (), ulPort));
+          serverApps.Add (ulPacketSinkHelper.Install (remoteHost));
+
+          Ptr<EpcTft> tft = Create<EpcTft> ();
+          EpcTft::PacketFilter dlpf;
+          dlpf.localPortStart = dlPort;
+          dlpf.localPortEnd = dlPort;
+          tft->Add (dlpf);
+          EpcTft::PacketFilter ulpf;
+          ulpf.remotePortStart = ulPort;
+          ulpf.remotePortEnd = ulPort;
+          tft->Add (ulpf);
+          EpsBearer bearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
+          lteHelper->ActivateDedicatedEpsBearer (ueLteDevs.Get (u), bearer, tft);
+
+          Time startTime = Seconds (startTimeSeconds->GetValue ());
+          serverApps.Start (startTime);
+          clientApps.Start (startTime);
+        }
+    }
+
+  //Test SpectrumPhy to get signals form DL channel
+  Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testDlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  Ptr<LteEnbNetDevice> eNbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
+  testDlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetDlEarfcn (), m_dlBandwidth));
+  dlChannel->AddRx (testDlSpectrumPhy);
+
+  testDlSpectrumPhy->SetCellId (2);
+
+  testDlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&DlDataRxStartNofiticationArea, this));
+
+  //Test SpectrumPhy to get signals form UL channel
+  Ptr<LteSpectrumPhy> ueUlSpectrumPhy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetUplinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
+  Ptr<SpectrumChannel> ulChannel = ueUlSpectrumPhy->GetChannel ();
+
+  Ptr<LteSimpleSpectrumPhy> testUlSpectrumPhy = CreateObject<LteSimpleSpectrumPhy> ();
+  testUlSpectrumPhy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (eNbDev->GetUlEarfcn (), m_ulBandwidth));
+  ulChannel->AddRx (testUlSpectrumPhy);
+
+  testUlSpectrumPhy->SetCellId (2);
+
+  testUlSpectrumPhy->TraceConnectWithoutContext ("RxStart",
+                                                 MakeBoundCallback (&UlDataRxStartNofiticationArea, this));
+
+  double expectedDlPowerCenterArea = 1.0;
+  std::vector<bool> expectedDlRbCenterArea;
+  expectedDlRbCenterArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbCenterArea;
+  expectedUlRbCenterArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 0; i < m_dlBandwidth; i++)
+    {
+      expectedDlRbCenterArea[i] = true;
+      expectedUlRbCenterArea[i] = true;
+    }
+
+  double expectedDlPowerEdgeArea = 2.0;
+  std::vector<bool> expectedDlRbEdgeArea;
+  expectedDlRbEdgeArea.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbEdgeArea;
+  expectedUlRbEdgeArea.resize (m_ulBandwidth, false);
+  for (uint32_t i = 0; i < 6; i++)
+    {
+      expectedDlRbEdgeArea[i] = true;
+      expectedUlRbEdgeArea[i] = true;
+    }
+
+  std::vector<bool> expectedDlRbEdgeArea2;
+  expectedDlRbEdgeArea2.resize (m_dlBandwidth, false);
+  std::vector<bool> expectedUlRbEdgeArea2;
+  expectedUlRbEdgeArea2.resize (m_dlBandwidth, false);
+  for (uint32_t i = 6; i < 12; i++)
+    {
+      expectedDlRbEdgeArea2[i] = true;
+      expectedUlRbEdgeArea2[i] = true;
+    }
+
+
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::TeleportUe, this, 800, 0,
+                       expectedDlPowerCenterArea, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (1),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0225815, expectedUlRbCenterArea );
+
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::TeleportUe, this, 400, 0,
+                       expectedDlPowerEdgeArea, expectedDlRbEdgeArea );
+  Simulator::Schedule (MilliSeconds (501),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.135489, expectedUlRbEdgeArea );
+
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::TeleportUe2, this, ueNodes1.Get (0), 600, 0,
+                       expectedDlPowerEdgeArea, expectedDlRbEdgeArea2 );
+  Simulator::Schedule (MilliSeconds (1001),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.135489, expectedUlRbEdgeArea2 );
+
+  Simulator::Schedule (MilliSeconds (1501),
+                       &LteFrAreaTestCase::TeleportUe2, this, ueNodes1.Get (0), 200, 0,
+                       expectedDlPowerEdgeArea, expectedDlRbEdgeArea );
+  Simulator::Schedule (MilliSeconds (1501),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.135489, expectedUlRbEdgeArea );
+
+  Simulator::Schedule (MilliSeconds (2001),
+                       &LteFrAreaTestCase::TeleportUe, this, 800, 0,
+                       expectedDlPowerCenterArea, expectedDlRbCenterArea );
+  Simulator::Schedule (MilliSeconds (2001),
+                       &LteFrAreaTestCase::SetUlExpectedValues, this, 0.0225815, expectedUlRbCenterArea );
+
+  Simulator::Stop (Seconds (2.500));
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongDlRbg, false,
+                         "Scheduler used DL RBG muted by FFR Algorithm");
+
+  NS_TEST_ASSERT_MSG_EQ (m_usedWrongUlRbg, false,
+                         "Scheduler used UL RB muted by FFR Algorithm");
+
+  Simulator::Destroy ();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-frequency-reuse.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,211 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_TEST_DOWNLINK_FR_H
+#define LTE_TEST_DOWNLINK_FR_H
+
+#include "ns3/test.h"
+#include "ns3/spectrum-value.h"
+#include <ns3/lte-rrc-sap.h>
+
+#include "ns3/spectrum-test.h"
+#include "ns3/lte-spectrum-value-helper.h"
+
+using namespace ns3;
+
+/**
+ * Test Downlink FFR algorithms
+ */
+class LteFrequencyReuseTestSuite : public TestSuite
+{
+public:
+  LteFrequencyReuseTestSuite ();
+};
+
+class LteFrTestCase : public TestCase
+{
+public:
+  LteFrTestCase (std::string name,
+                 uint32_t userNum,uint8_t dlBandwidth,uint8_t ulBandwidth,
+                 std::vector<bool> availableDlRb, std::vector<bool> availableUlRb);
+  virtual ~LteFrTestCase ();
+
+  void DlDataRxStart (Ptr<const SpectrumValue> spectrumValue);
+  void UlDataRxStart (Ptr<const SpectrumValue> spectrumValue);
+
+protected:
+  virtual void DoRun (void);
+
+  uint32_t m_userNum;
+  uint8_t m_dlBandwidth;
+  uint8_t m_ulBandwidth;
+
+  std::vector<bool> m_availableDlRb;
+  bool m_usedMutedDlRbg;
+
+  std::vector<bool> m_availableUlRb;
+  bool m_usedMutedUlRbg;
+};
+
+
+class LteHardFrTestCase : public LteFrTestCase
+{
+public:
+  LteHardFrTestCase (std::string name, uint32_t userNum,
+                     std::string schedulerType,
+                     uint8_t dlBandwidth, uint8_t ulBandwidth,
+                     uint8_t dlSubBandOffset, uint8_t dlSubBandwidth,
+                     uint8_t ulSubBandOffset, uint8_t ulSubBandwidth,
+                     std::vector<bool> availableDlRb, std::vector<bool> availableUlRb);
+  virtual ~LteHardFrTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+  std::string m_schedulerType;
+
+  uint8_t m_dlSubBandOffset;
+  uint8_t m_dlSubBandwidth;
+
+  uint8_t m_ulSubBandOffset;
+  uint8_t m_ulSubBandwidth;
+};
+
+class LteStrictFrTestCase : public LteFrTestCase
+{
+public:
+  LteStrictFrTestCase (std::string name, uint32_t userNum,
+                       std::string schedulerType,
+                       uint8_t dlBandwidth, uint8_t ulBandwidth,
+                       uint8_t dlCommonSubBandwidth, uint8_t dlEdgeSubBandOffset, uint8_t dlEdgeSubBandwidth,
+                       uint8_t ulCommonSubBandwidth, uint8_t ulEdgeSubBandOffset, uint8_t ulEdgeSubBandwidth,
+                       std::vector<bool> availableDlRb, std::vector<bool> availableUlRb);
+  virtual ~LteStrictFrTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+  std::string m_schedulerType;
+
+  uint8_t m_dlCommonSubBandwidth;
+  uint8_t m_dlEdgeSubBandOffset;
+  uint8_t m_dlEdgeSubBandwidth;
+
+  uint8_t m_ulCommonSubBandwidth;
+  uint8_t m_ulEdgeSubBandOffset;
+  uint8_t m_ulEdgeSubBandwidth;
+};
+
+class LteFrAreaTestCase : public TestCase
+{
+public:
+  LteFrAreaTestCase (std::string name, std::string schedulerType);
+  virtual ~LteFrAreaTestCase ();
+
+  void DlDataRxStart (Ptr<const SpectrumValue> spectrumValue);
+  void UlDataRxStart (Ptr<const SpectrumValue> spectrumValue);
+
+  void SimpleTeleportUe (uint32_t x, uint32_t y);
+  void TeleportUe (uint32_t x, uint32_t y, double expectedPower, std::vector<bool> expectedDlRb);
+  void TeleportUe2 (Ptr<Node> ueNode, uint32_t x, uint32_t y, double expectedPower,
+                    std::vector<bool> expectedDlRb);
+
+  void SetDlExpectedValues (double expectedPower, std::vector<bool> expectedDlRb);
+  void SetUlExpectedValues (double expectedPower, std::vector<bool> expectedDlRb);
+
+protected:
+  virtual void DoRun (void);
+
+  std::string m_schedulerType;
+
+  uint8_t m_dlBandwidth;
+  uint8_t m_ulBandwidth;
+
+  Time m_teleportTime;
+  Ptr<MobilityModel> m_ueMobility;
+
+  double m_expectedDlPower;
+  std::vector<bool> m_expectedDlRb;
+  bool m_usedWrongDlRbg;
+  bool m_usedWrongDlPower;
+
+  double m_expectedUlPower;
+  std::vector<bool> m_expectedUlRb;
+  bool m_usedWrongUlRbg;
+  bool m_usedWrongUlPower;
+
+};
+
+class LteStrictFrAreaTestCase : public LteFrAreaTestCase
+{
+public:
+  LteStrictFrAreaTestCase (std::string name, std::string schedulerType);
+  virtual ~LteStrictFrAreaTestCase ();
+
+private:
+  virtual void DoRun (void);
+};
+
+class LteSoftFrAreaTestCase : public LteFrAreaTestCase
+{
+public:
+  LteSoftFrAreaTestCase (std::string name, std::string schedulerType);
+  virtual ~LteSoftFrAreaTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+};
+
+class LteSoftFfrAreaTestCase : public LteFrAreaTestCase
+{
+public:
+  LteSoftFfrAreaTestCase (std::string name, std::string schedulerType);
+  virtual ~LteSoftFfrAreaTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+};
+
+class LteEnhancedFfrAreaTestCase : public LteFrAreaTestCase
+{
+public:
+  LteEnhancedFfrAreaTestCase (std::string name, std::string schedulerType);
+  virtual ~LteEnhancedFfrAreaTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+};
+
+class LteDistributedFfrAreaTestCase : public LteFrAreaTestCase
+{
+public:
+  LteDistributedFfrAreaTestCase (std::string name, std::string schedulerType);
+  virtual ~LteDistributedFfrAreaTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+};
+
+#endif /* LTE_TEST_DOWNLINK_FR_H */
--- a/src/lte/test/lte-test-harq.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-harq.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -111,6 +111,9 @@
   Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
   Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (true));
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
 //   Config::SetDefault ("ns3::RrFfMacScheduler::HarqEnabled", BooleanValue (false));
 //   LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
 //   LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
@@ -124,7 +127,7 @@
 
 //   LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
 //   LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
+//   LogComponentEnable ("LteChunkProcessor", LOG_LEVEL_ALL);
 //
 //   LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
 //   LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-interference-fr.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,413 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ * Based on lte-test-interference.{h,cc} by Manuel Requena <manuel.requena@cttc.es>
+ *                                                                              Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+#include "ns3/string.h"
+#include "ns3/double.h"
+#include <ns3/enum.h>
+#include "ns3/boolean.h"
+#include <ns3/pointer.h>
+#include "ns3/mobility-helper.h"
+#include "ns3/lte-helper.h"
+#include "ns3/ff-mac-scheduler.h"
+
+#include "ns3/lte-enb-phy.h"
+#include "ns3/lte-enb-net-device.h"
+
+#include "ns3/lte-ue-phy.h"
+#include "ns3/lte-ue-net-device.h"
+
+#include "lte-test-interference-fr.h"
+
+#include "lte-test-sinr-chunk-processor.h"
+
+#include "lte-simple-spectrum-phy.h"
+#include "ns3/spectrum-value.h"
+#include "ns3/lte-spectrum-value-helper.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("LteInterferenceFrTest");
+
+using namespace ns3;
+
+/**
+ * TestSuite
+ */
+
+LteInterferenceFrTestSuite::LteInterferenceFrTestSuite ()
+  : TestSuite ("lte-interference-fr", SYSTEM)
+{
+//  LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_DEBUG);
+//  LogComponentEnable ("LteInterferenceFrTest", logLevel);
+
+  AddTestCase (new LteInterferenceHardFrTestCase ("d1=50, d2=20",  50.000000, 20.000000,  356449.932732, 10803.280215), TestCase::QUICK);
+  AddTestCase (new LteInterferenceHardFrTestCase ("d1=50, d2=50",  50.000000, 50.000000,  356449.932732, 10803.280215), TestCase::QUICK);
+  AddTestCase (new LteInterferenceHardFrTestCase ("d1=50, d2=200",  50.000000, 200.000000,  356449.932732, 10803.280215), TestCase::QUICK);
+  AddTestCase (new LteInterferenceHardFrTestCase ("d1=50, d2=500",  50.000000, 500.000000,  356449.932732, 10803.280215), TestCase::QUICK);
+
+  AddTestCase (new LteInterferenceStrictFrTestCase ("d1=50, d2=20",  50.000000, 20.000000,  0.160000, 0.159998, 356449.932732, 10803.280215, 18), TestCase::QUICK);
+  AddTestCase (new LteInterferenceStrictFrTestCase ("d1=50, d2=50",  50.000000, 50.000000, 0.999997, 0.999907, 356449.932732, 10803.280215, 28), TestCase::QUICK);
+  AddTestCase (new LteInterferenceStrictFrTestCase ("d1=50, d2=200",  50.000000, 200.000000,  15.999282, 15.976339, 356449.932732, 10803.280215, 30), TestCase::QUICK);
+  AddTestCase (new LteInterferenceStrictFrTestCase ("d1=50, d2=500",  50.000000, 500.000000,  99.971953, 99.082845, 356449.932732, 10803.280215, 30), TestCase::QUICK);
+
+}
+
+static LteInterferenceFrTestSuite LteInterferenceFrTestSuite;
+
+
+/**
+ * TestCase Data
+ */
+LteInterferenceHardFrTestCase::LteInterferenceHardFrTestCase (std::string name, double d1, double d2, double dlSinr, double ulSinr)
+  : TestCase ("Test: " + name),
+    m_d1 (d1),
+    m_d2 (d2),
+    m_dlSinrDb (10 * std::log10 (dlSinr)),
+    m_ulSinrDb (10 * std::log10 (ulSinr))
+{
+  NS_LOG_INFO ("Creating LteInterferenceFrTestCase");
+}
+
+LteInterferenceHardFrTestCase::~LteInterferenceHardFrTestCase ()
+{
+}
+
+void
+LteInterferenceHardFrTestCase::DoRun (void)
+{
+  NS_LOG_INFO (this << GetName ());
+  NS_LOG_DEBUG ("LteInterferenceHardFrTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
+
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
+  Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrHardAlgorithm");
+
+  lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes1;
+  NodeContainer ueNodes2;
+  enbNodes.Create (2);
+  ueNodes1.Create (1);
+  ueNodes2.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2);
+
+  // the topology is the following:
+  //         d2
+  //  UE1-----------eNB2
+  //   |             |
+  // d1|             |d1
+  //   |     d2      |
+  //  eNB1----------UE2
+  //
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));   // eNB1
+  positionAlloc->Add (Vector (m_d2, m_d1, 0.0)); // eNB2
+  positionAlloc->Add (Vector (0.0, m_d1, 0.0));  // UE1
+  positionAlloc->Add (Vector (m_d2, 0.0, 0.0));  // UE2
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs1;
+  NetDeviceContainer ueDevs2;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+  lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandwidth", UintegerValue (12));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandwidth", UintegerValue (25));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandOffset", UintegerValue (12));
+  lteHelper->SetFfrAlgorithmAttribute ("DlSubBandwidth", UintegerValue (12));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("UlSubBandwidth", UintegerValue (25));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
+
+  ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
+  ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
+
+  lteHelper->Attach (ueDevs1, enbDevs.Get (0));
+  lteHelper->Attach (ueDevs2, enbDevs.Get (1));
+
+  // Activate an EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs1, bearer);
+  lteHelper->ActivateDataRadioBearer (ueDevs2, bearer);
+
+  // Use testing chunk processor in the PHY layer
+  // It will be used to test that the SNR is as intended
+  // we plug in two instances, one for DL and one for UL
+
+  Ptr<LtePhy> ue1Phy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+  Ptr<LteTestSinrChunkProcessor> testDlSinr1 = Create<LteTestSinrChunkProcessor> ();
+  ue1Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr1);
+
+  Ptr<LtePhy> enb1phy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+  Ptr<LteTestSinrChunkProcessor> testUlSinr1 = Create<LteTestSinrChunkProcessor> ();
+  enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr1);
+
+  // same as above for eNB2 and UE2
+
+  Ptr<LtePhy> ue2Phy = ueDevs2.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+  Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> ();
+  ue2Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr2);
+
+  Ptr<LtePhy> enb2phy = enbDevs.Get (1)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+  Ptr<LteTestSinrChunkProcessor> testUlSinr2 = Create<LteTestSinrChunkProcessor> ();
+  enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr2);
+
+// need to allow for RRC connection establishment + SRS
+  Simulator::Stop (Seconds (0.200));
+  Simulator::Run ();
+
+
+  for (uint32_t i = 0; i < 12; i++)
+    {
+      double dlSinr1 = testDlSinr1->GetSinr ()->operator[] (i);
+      double dlSinr1Db = 10.0 * std::log10 (dlSinr1);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr1Db, m_dlSinrDb, 0.01, "Wrong SINR in DL! (eNB1 --> UE1)");
+
+
+      double dlSinr2 = testDlSinr2->GetSinr ()->operator[] (i);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr2, 0, 0.01, "Wrong SINR in DL! (eNB2 --> UE2)");
+    }
+
+  for (uint32_t i = 12; i < 24; i++)
+    {
+      double dlSinr1 = testDlSinr1->GetSinr ()->operator[] (i);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr1, 0, 0.01, "Wrong SINR in DL! (eNB1 --> UE1)");
+
+      double dlSinr2 = testDlSinr2->GetSinr ()->operator[] (i);
+      double dlSinr2Db = 10.0 * std::log10 (dlSinr2);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr2Db, m_dlSinrDb, 0.01, "Wrong SINR in DL! (eNB2 --> UE2)");
+    }
+
+  //FR algorithms do not operate in uplink now, so we do not test it
+//  double ulSinr1Db = 10.0 * std::log10 (testUlSinr1->GetSinr ()->operator[] (0));
+//  NS_LOG_DEBUG("ulSinr1Db: "<< ulSinr1Db);
+//  NS_TEST_ASSERT_MSG_EQ_TOL (ulSinr1Db, m_ulSinrDb, 0.01, "Wrong SINR in UL!  (UE1 --> eNB1)");
+//
+//  double ulSinr2Db = 10.0 * std::log10 (testUlSinr2->GetSinr ()->operator[] (0));
+//  NS_LOG_DEBUG("ulSinr2Db: "<< ulSinr2Db);
+//  NS_TEST_ASSERT_MSG_EQ_TOL (ulSinr2Db, m_ulSinrDb, 0.01, "Wrong SINR in UL!  (UE2 --> eNB2)");
+
+  Simulator::Destroy ();
+}
+
+LteInterferenceStrictFrTestCase::LteInterferenceStrictFrTestCase (std::string name, double d1, double d2,
+                                                                  double commonDlSinr, double commonUlSinr, double edgeDlSinr, double edgeUlSinr,
+                                                                  uint32_t rspqThreshold)
+  : TestCase ("Test: " + name),
+    m_d1 (d1),
+    m_d2 (d2),
+    m_commonDlSinrDb (10 * std::log10 (commonDlSinr)),
+    m_commonUlSinrDb (10 * std::log10 (commonUlSinr)),
+    m_edgeDlSinrDb (10 * std::log10 (edgeDlSinr)),
+    m_edgeUlSinrDb (10 * std::log10 (edgeUlSinr)),
+    m_rspqThreshold (rspqThreshold)
+{
+  NS_LOG_INFO ("Creating LteInterferenceFrTestCase");
+}
+
+LteInterferenceStrictFrTestCase::~LteInterferenceStrictFrTestCase ()
+{
+}
+
+void
+LteInterferenceStrictFrTestCase::DoRun (void)
+{
+  NS_LOG_INFO (this << GetName ());
+  NS_LOG_DEBUG ("LteInterferenceStrictFrTestCase");
+
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
+  Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFrStrictAlgorithm");
+  lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (m_rspqThreshold));
+  lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+  lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
+                                       UintegerValue (LteRrcSap::PdschConfigDedicated::dB0));
+
+
+  lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes1;
+  NodeContainer ueNodes2;
+  enbNodes.Create (2);
+  ueNodes1.Create (2);
+  ueNodes2.Create (2);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2);
+
+  // the topology is the following:
+  //         d2
+  //  UE1-----------eNB2
+  //   |             |
+  // d1|             |d1
+  //   |     d2      |
+  //  eNB1----------UE2
+  //
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0,  0.0,  0.0));  // eNB1
+  positionAlloc->Add (Vector (m_d2, m_d1, 0.0));  // eNB2
+
+  positionAlloc->Add (Vector (0.0, m_d1, 0.0));  // UE1-eNB1
+  positionAlloc->Add (Vector (0.5 * m_d2, 0.0, 0.0));  // UE2-eNB1
+
+  positionAlloc->Add (Vector (m_d2, 0.0, 0.0));   // UE1-eNB2
+  positionAlloc->Add (Vector (0.5 * m_d2, m_d1, 0.0));    // UE2-eNB2
+
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs1;
+  NetDeviceContainer ueDevs2;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+  lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
+
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlCommonSubBandwidth", UintegerValue (12));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("UlCommonSubBandwidth", UintegerValue (25));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandOffset", UintegerValue (0));
+  lteHelper->SetFfrAlgorithmAttribute ("UlEdgeSubBandwidth", UintegerValue (0));
+
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
+
+  lteHelper->SetFfrAlgorithmAttribute ("DlCommonSubBandwidth", UintegerValue (12));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandOffset", UintegerValue (6));
+  lteHelper->SetFfrAlgorithmAttribute ("DlEdgeSubBandwidth", UintegerValue (6));
+  enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
+
+  ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
+  ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
+
+  lteHelper->Attach (ueDevs1, enbDevs.Get (0));
+  lteHelper->Attach (ueDevs2, enbDevs.Get (1));
+
+  // Activate an EPS bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs1, bearer);
+  lteHelper->ActivateDataRadioBearer (ueDevs2, bearer);
+
+  // Use testing chunk processor in the PHY layer
+  // It will be used to test that the SNR is as intended
+  // we plug in two instances, one for DL and one for UL
+
+  Ptr<LtePhy> ue1Phy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+  Ptr<LteTestSinrChunkProcessor> testDlSinr1 = Create<LteTestSinrChunkProcessor> ();
+  ue1Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr1);
+
+  Ptr<LtePhy> enb1phy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+  Ptr<LteTestSinrChunkProcessor> testUlSinr1 = Create<LteTestSinrChunkProcessor> ();
+  enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr1);
+
+  // same as above for eNB2 and UE2
+
+  Ptr<LtePhy> ue2Phy = ueDevs2.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+  Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> ();
+  ue2Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr2);
+
+  Ptr<LtePhy> enb2phy = enbDevs.Get (1)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
+  Ptr<LteTestSinrChunkProcessor> testUlSinr2 = Create<LteTestSinrChunkProcessor> ();
+  enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr2);
+
+// need to allow for UE Measurement report
+  Simulator::Stop (Seconds (2.000));
+  Simulator::Run ();
+
+
+  for (uint32_t i = 0; i < 12; i++)
+    {
+      double dlSinr1 = testDlSinr1->GetSinr ()->operator[] (i);
+      double dlSinr1Db = 10.0 * std::log10 (dlSinr1);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr1Db, m_commonDlSinrDb, 0.01, "Wrong SINR in DL! (eNB1 --> UE1)");
+
+
+      double dlSinr2 = testDlSinr2->GetSinr ()->operator[] (i);
+      double dlSinr2Db = 10.0 * std::log10 (dlSinr2);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr2Db, m_commonDlSinrDb, 0.01, "Wrong SINR in DL! (eNB2 --> UE2)");
+    }
+
+  for (uint32_t i = 12; i < 18; i++)
+    {
+      double dlSinr1 = testDlSinr1->GetSinr ()->operator[] (i);
+      double dlSinr1Db = 10.0 * std::log10 (dlSinr1);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr1Db, m_edgeDlSinrDb, 0.01, "Wrong SINR in DL! (eNB1 --> UE1)");
+
+
+      double dlSinr2 = testDlSinr2->GetSinr ()->operator[] (i);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr2, 0, 0.01, "Wrong SINR in DL! (eNB2 --> UE2)");
+    }
+
+  for (uint32_t i = 18; i < 24; i++)
+    {
+      double dlSinr1 = testDlSinr1->GetSinr ()->operator[] (i);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr1, 0, 0.01, "Wrong SINR in DL! (eNB1 --> UE1)");
+
+      double dlSinr2 = testDlSinr2->GetSinr ()->operator[] (i);
+      double dlSinr2Db = 10.0 * std::log10 (dlSinr2);
+      NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr2Db, m_edgeDlSinrDb, 0.01, "Wrong SINR in DL! (eNB2 --> UE2)");
+    }
+
+
+  //FR algorithms do not operate in uplink now, so we do not test it
+//  double ulSinr1Db = 10.0 * std::log10 (testUlSinr1->GetSinr ()->operator[] (0));
+//  NS_LOG_DEBUG("ulSinr1Db: "<< ulSinr1Db);
+//  NS_TEST_ASSERT_MSG_EQ_TOL (ulSinr1Db, m_ulSinrDb, 0.01, "Wrong SINR in UL!  (UE1 --> eNB1)");
+//
+//  double ulSinr2Db = 10.0 * std::log10 (testUlSinr2->GetSinr ()->operator[] (0));
+//  NS_LOG_DEBUG("ulSinr2Db: "<< ulSinr2Db);
+//  NS_TEST_ASSERT_MSG_EQ_TOL (ulSinr2Db, m_ulSinrDb, 0.01, "Wrong SINR in UL!  (UE2 --> eNB2)");
+
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-interference-fr.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,77 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ * Based on lte-test-interference.{h,cc} by Manuel Requena <manuel.requena@cttc.es>
+ *                                          Nicola Baldo <nbaldo@cttc.es>
+ *
+ */
+
+#ifndef LTE_TEST_INTERFERENCE_FR_H
+#define LTE_TEST_INTERFERENCE_FR_H
+
+#include "ns3/test.h"
+
+using namespace ns3;
+
+/**
+ * Test Interference level with FR algorithms
+ */
+class LteInterferenceFrTestSuite : public TestSuite
+{
+public:
+  LteInterferenceFrTestSuite ();
+};
+
+
+class LteInterferenceHardFrTestCase : public TestCase
+{
+public:
+  LteInterferenceHardFrTestCase (std::string name, double d1, double d2, double dlSinr, double ulSinr);
+  virtual ~LteInterferenceHardFrTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+  double m_d1;
+  double m_d2;
+  double m_dlSinrDb;
+  double m_ulSinrDb;
+};
+
+class LteInterferenceStrictFrTestCase : public TestCase
+{
+public:
+  LteInterferenceStrictFrTestCase (std::string name, double d1, double d2,
+                                   double commonDlSinr, double commonUlSinr, double edgeDlSinr, double edgeUlSinr,
+                                   uint32_t rspqThreshold);
+  virtual ~LteInterferenceStrictFrTestCase ();
+
+private:
+  virtual void DoRun (void);
+
+  double m_d1;
+  double m_d2;
+  double m_commonDlSinrDb;
+  double m_commonUlSinrDb;
+  double m_edgeDlSinrDb;
+  double m_edgeUlSinrDb;
+
+  uint32_t m_rspqThreshold;
+};
+
+#endif /* LTE_TEST_INTERFERENCE_FR_H */
--- a/src/lte/test/lte-test-interference.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-interference.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -120,6 +120,9 @@
   lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
   lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (false));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   // Create Nodes: eNodeB and UE
   NodeContainer enbNodes;
   NodeContainer ueNodes1;
@@ -171,11 +174,11 @@
   // we plug in two instances, one for DL and one for UL
 
   Ptr<LtePhy> ue1Phy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testDlSinr1 = Create<LteTestSinrChunkProcessor> (ue1Phy);
+  Ptr<LteTestSinrChunkProcessor> testDlSinr1 = Create<LteTestSinrChunkProcessor> ();
   ue1Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr1);
 
   Ptr<LtePhy> enb1phy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testUlSinr1 = Create<LteTestSinrChunkProcessor> (enb1phy);
+  Ptr<LteTestSinrChunkProcessor> testUlSinr1 = Create<LteTestSinrChunkProcessor> ();
   enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr1);
 
   Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
@@ -188,11 +191,11 @@
   // same as above for eNB2 and UE2
 
   Ptr<LtePhy> ue2Phy = ueDevs2.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> (ue2Phy);
+  Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> ();
   ue2Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr2);
 
   Ptr<LtePhy> enb2phy = enbDevs.Get (1)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testUlSinr2 = Create<LteTestSinrChunkProcessor> (enb2phy);
+  Ptr<LteTestSinrChunkProcessor> testUlSinr2 = Create<LteTestSinrChunkProcessor> ();
   enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr2);
 
   Config::Connect ("/NodeList/1/DeviceList/0/LteEnbMac/DlScheduling",
--- a/src/lte/test/lte-test-link-adaptation.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-link-adaptation.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -162,6 +162,9 @@
   Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (2));
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /**
     * Simulation Topology
     */
@@ -204,7 +207,7 @@
   // Use testing chunk processor in the PHY layer
   // It will be used to test that the SNR is as intended
   Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> (uePhy);
+  Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> ();
   uePhy->GetDownlinkSpectrumPhy ()->AddCtrlSinrChunkProcessor (testSinr);
 
   Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
--- a/src/lte/test/lte-test-mimo.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-mimo.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -121,6 +121,9 @@
   Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (m_useIdealRrc));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
--- a/src/lte/test/lte-test-pathloss-model.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-pathloss-model.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -25,7 +25,7 @@
 #include "ns3/spectrum-test.h"
 
 #include "ns3/lte-phy-tag.h"
-#include "ns3/lte-sinr-chunk-processor.h"
+#include "ns3/lte-chunk-processor.h"
 
 
 #include <ns3/hybrid-buildings-propagation-loss-model.h>
@@ -36,6 +36,7 @@
 #include <ns3/single-model-spectrum-channel.h>
 #include "ns3/string.h"
 #include "ns3/double.h"
+#include <ns3/boolean.h>
 #include <ns3/building.h>
 #include <ns3/enum.h>
 #include <ns3/net-device-container.h>
@@ -205,6 +206,8 @@
   /**
   * Simulation Topology
   */
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
 
   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
   //   lteHelper->EnableLogComponents ();
@@ -269,7 +272,7 @@
   // Use testing chunk processor in the PHY layer
   // It will be used to test that the SNR is as intended
   //Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> (uePhy);
+  Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> ();
   uePhy->GetDownlinkSpectrumPhy ()->AddCtrlSinrChunkProcessor (testSinr);
    
 //   Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
--- a/src/lte/test/lte-test-phy-error-model.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-phy-error-model.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -169,6 +169,9 @@
   Config::SetDefault ("ns3::RrFfMacScheduler::HarqEnabled", BooleanValue (false));
   Config::SetGlobal ("RngRun", IntegerValue (m_rngRun));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /*
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
@@ -322,6 +325,9 @@
   Config::SetDefault ("ns3::RrFfMacScheduler::HarqEnabled", BooleanValue (false));
   Config::SetGlobal ("RngRun", IntegerValue (m_rngRun));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /*
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
--- a/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -188,6 +188,9 @@
   // This is needed as the RR scheduler does not allocate resources properly for retransmission
   Config::SetDefault ("ns3::LteRlcAm::TxOpportunityForRetxAlwaysBigEnough", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
--- a/src/lte/test/lte-test-sinr-chunk-processor.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-sinr-chunk-processor.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -20,7 +20,7 @@
  */
 
 #include <ns3/log.h>
-
+#include <ns3/spectrum-value.h>
 #include "lte-test-sinr-chunk-processor.h"
 
 NS_LOG_COMPONENT_DEFINE ("LteTestSinrChunkProcessor");
@@ -28,11 +28,9 @@
 namespace ns3 {
 
 
-LteTestSinrChunkProcessor::LteTestSinrChunkProcessor (Ptr<LtePhy> p)
-  : m_phy (p)
+LteTestSinrChunkProcessor::LteTestSinrChunkProcessor ()
 {
-  NS_LOG_FUNCTION (this << p);
-  NS_ASSERT (m_phy);
+  NS_LOG_FUNCTION (this);
 }
 
 LteTestSinrChunkProcessor::~LteTestSinrChunkProcessor ()
@@ -41,6 +39,12 @@
 }
 
 void
+LteTestSinrChunkProcessor::AddCallback (LteChunkProcessorCallback c)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
 LteTestSinrChunkProcessor::Start ()
 {
   NS_LOG_FUNCTION (this);
@@ -49,7 +53,7 @@
 }
 
 void
-LteTestSinrChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
+LteTestSinrChunkProcessor::EvaluateChunk (const SpectrumValue& sinr, Time duration)
 {
   NS_LOG_FUNCTION (this << sinr << duration);
   if (m_sumSinr == 0)
--- a/src/lte/test/lte-test-sinr-chunk-processor.h	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-sinr-chunk-processor.h	Fri Sep 05 01:12:55 2014 +0200
@@ -22,24 +22,24 @@
 #ifndef LTE_TEST_SINR_CHUNK_PROCESSOR_H
 #define LTE_TEST_SINR_CHUNK_PROCESSOR_H
 
-#include "ns3/lte-sinr-chunk-processor.h"
+#include "ns3/lte-chunk-processor.h"
 
 namespace ns3 {
 
-
 /**
- * This custom LteSinrChunkProcessor averages the calculated SINR over time.
+ * This custom LteTestSinrChunkProcessor averages the calculated SINR over time.
  * It is plugged on the receiving SpectrumPhy and therefore
  * receives the SINR SpectrumValue calculated by the LteInterference module.
  */
-class LteTestSinrChunkProcessor : public LteSinrChunkProcessor
+class LteTestSinrChunkProcessor : public LteChunkProcessor
 {
 public:
-  LteTestSinrChunkProcessor (Ptr<LtePhy> p);
+  LteTestSinrChunkProcessor ();
   virtual ~LteTestSinrChunkProcessor ();
 
+  virtual void AddCallback (LteChunkProcessorCallback c);
   virtual void Start ();
-  virtual void EvaluateSinrChunk (const SpectrumValue& sinr, Time duration);
+  virtual void EvaluateChunk (const SpectrumValue& sinr, Time duration);
   virtual void End ();
 
   Ptr<SpectrumValue> GetSinr ();
@@ -48,7 +48,6 @@
   Ptr<SpectrumValue> m_sumSinr;
   Ptr<SpectrumValue> m_sinr;
   Time m_totDuration;
-  Ptr<LtePhy> m_phy;
 };
 
 
--- a/src/lte/test/lte-test-tdbet-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-tdbet-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -207,6 +207,9 @@
 
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
--- a/src/lte/test/lte-test-tdmt-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-tdmt-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -192,6 +192,9 @@
 
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
--- a/src/lte/test/lte-test-tta-ff-mac-scheduler.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-tta-ff-mac-scheduler.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -195,6 +195,9 @@
 
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
--- a/src/lte/test/lte-test-ue-measurements.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-ue-measurements.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -147,6 +147,9 @@
   lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
   lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (false));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   // LogComponentEnable ("LteUeMeasurementsTest", LOG_LEVEL_ALL);
 
   // Create Nodes: eNodeB and UE
@@ -201,11 +204,11 @@
   // we plug in two instances, one for DL and one for UL
 
   Ptr<LtePhy> ue1Phy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testDlSinr1 = Create<LteTestSinrChunkProcessor> (ue1Phy);
+  Ptr<LteTestSinrChunkProcessor> testDlSinr1 = Create<LteTestSinrChunkProcessor> ();
   ue1Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr1);
 
   Ptr<LtePhy> enb1phy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testUlSinr1 = Create<LteTestSinrChunkProcessor> (enb1phy);
+  Ptr<LteTestSinrChunkProcessor> testUlSinr1 = Create<LteTestSinrChunkProcessor> ();
   enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr1);
 
   Config::Connect ("/NodeList/2/DeviceList/0/LteUePhy/ReportUeMeasurements",
@@ -216,11 +219,11 @@
   // same as above for eNB2 and UE2
 
   Ptr<LtePhy> ue2Phy = ueDevs2.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> (ue2Phy);
+  Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> ();
   ue2Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr2);
 
   Ptr<LtePhy> enb2phy = enbDevs.Get (1)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testUlSinr2 = Create<LteTestSinrChunkProcessor> (enb2phy);
+  Ptr<LteTestSinrChunkProcessor> testUlSinr2 = Create<LteTestSinrChunkProcessor> ();
   enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr2);
 
   Config::Connect ("/NodeList/3/DeviceList/0/LteUePhy/ReportUeMeasurements",
@@ -574,6 +577,9 @@
                            StringValue ("ns3::FriisSpectrumPropagationLossModel"));
   lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   // Create Nodes: eNodeB and UE
   NodeContainer enbNodes;
   NodeContainer ueNodes;
@@ -1156,6 +1162,9 @@
                            StringValue ("ns3::FriisSpectrumPropagationLossModel"));
   lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   // Create Nodes: eNodeB and UE
   NodeContainer enbNodes;
   NodeContainer ueNodes;
@@ -1706,6 +1715,10 @@
                            StringValue ("ns3::FriisSpectrumPropagationLossModel"));
   lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (true));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
+
   // Create Nodes: eNodeB and UE
   NodeContainer enbNodes;
   NodeContainer ueNodes;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-uplink-power-control.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,528 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#include <ns3/simulator.h>
+#include <ns3/log.h>
+#include <ns3/callback.h>
+#include <ns3/config.h>
+#include <ns3/string.h>
+#include <ns3/double.h>
+#include <ns3/enum.h>
+#include <ns3/boolean.h>
+#include <ns3/pointer.h>
+#include <ns3/integer.h>
+
+#include "ns3/mobility-helper.h"
+#include "ns3/lte-helper.h"
+
+#include <ns3/ff-mac-scheduler.h>
+#include <ns3/lte-enb-net-device.h>
+#include <ns3/lte-enb-phy.h>
+#include <ns3/lte-enb-rrc.h>
+#include <ns3/lte-ue-net-device.h>
+#include <ns3/lte-ue-phy.h>
+#include <ns3/lte-ue-rrc.h>
+
+#include "lte-ffr-simple.h"
+#include "lte-test-sinr-chunk-processor.h"
+#include <ns3/lte-common.h>
+
+#include "lte-test-uplink-power-control.h"
+#include <ns3/lte-rrc-sap.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteUplinkPowerControlTest");
+
+using namespace ns3;
+
+/**
+ * TestSuite
+ */
+
+LteUplinkPowerControlTestSuite::LteUplinkPowerControlTestSuite ()
+  : TestSuite ("lte-uplink-power-control", SYSTEM)
+{
+//  LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_DEBUG);
+//  LogComponentEnable ("LteUplinkPowerControlTest", logLevel);
+  NS_LOG_INFO ("Creating LteUplinkPowerControlTestSuite");
+
+  AddTestCase (new LteUplinkOpenLoopPowerControlTestCase ("OpenLoopTest1"), TestCase::QUICK);
+  AddTestCase (new LteUplinkClosedLoopPowerControlAbsoluteModeTestCase ("ClosedLoopAbsoluteModeTest1"), TestCase::QUICK);
+  AddTestCase (new LteUplinkClosedLoopPowerControlAccumulatedModeTestCase ("ClosedLoopAccumulatedModeTest1"), TestCase::QUICK);
+}
+
+static LteUplinkPowerControlTestSuite lteUplinkPowerControlTestSuite;
+
+/**
+ * TestCase Data
+ */
+void
+PuschTxPowerNofitication (LteUplinkPowerControlTestCase *testcase,
+                          uint16_t cellId, uint16_t rnti, double txPower)
+{
+  testcase->PuschTxPowerTrace (cellId, rnti, txPower);
+}
+
+void
+PucchTxPowerNofitication (LteUplinkPowerControlTestCase *testcase,
+                          uint16_t cellId, uint16_t rnti, double txPower)
+{
+  testcase->PucchTxPowerTrace (cellId, rnti, txPower);
+}
+
+void
+SrsTxPowerNofitication (LteUplinkPowerControlTestCase *testcase,
+                        uint16_t cellId, uint16_t rnti, double txPower)
+{
+  testcase->SrsTxPowerTrace (cellId, rnti, txPower);
+}
+
+LteUplinkPowerControlTestCase::LteUplinkPowerControlTestCase (std::string name)
+  : TestCase (name)
+{
+  NS_LOG_INFO ("Creating LteUplinkPowerControlTestCase");
+}
+
+LteUplinkPowerControlTestCase::~LteUplinkPowerControlTestCase ()
+{
+}
+
+void
+LteUplinkPowerControlTestCase::TeleportUe (uint32_t x, uint32_t y,
+                                           double expectedPuschTxPower, double expectedPucchTxPower, double expectedSrsTxPower)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("Teleport UE to : (" << x << ", " << y << ", 0)");
+
+  m_ueMobility->SetPosition (Vector (x, y, 0.0));
+  m_teleportTime = Simulator::Now ();
+
+  m_expectedPuschTxPower = expectedPuschTxPower;
+  m_expectedPucchTxPower = expectedPucchTxPower;
+  m_expectedSrsTxPower = expectedSrsTxPower;
+}
+
+void
+LteUplinkPowerControlTestCase::SetTpcConfiguration (uint32_t tpc, uint32_t tpcNum,
+                                                    double expectedPuschTxPower, double expectedPucchTxPower, double expectedSrsTxPower)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_teleportTime = Simulator::Now ();
+
+  m_expectedPuschTxPower = expectedPuschTxPower;
+  m_expectedPucchTxPower = expectedPucchTxPower;
+  m_expectedSrsTxPower = expectedSrsTxPower;
+
+  m_ffrSimple->SetTpc (tpc, tpcNum, m_accumulatedMode);
+}
+
+void
+LteUplinkPowerControlTestCase::PuschTxPowerTrace (uint16_t cellId, uint16_t rnti, double txPower)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("PuschTxPower : CellId: " << cellId << " RNTI: " << rnti << " PuschTxPower: " << txPower);
+  //wait because of RSRP filtering
+  if ( (Simulator::Now () - m_teleportTime ) < MilliSeconds (50))
+    {
+      return;
+    }
+  NS_TEST_ASSERT_MSG_EQ_TOL (txPower, m_expectedPuschTxPower, 0.01, "Wrong Pusch Tx Power");
+}
+
+void
+LteUplinkPowerControlTestCase::PucchTxPowerTrace (uint16_t cellId, uint16_t rnti, double txPower)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("PucchTxPower : CellId: " << cellId << " RNTI: " << rnti << " PuschTxPower: " << txPower);
+  //wait because of RSRP filtering
+  if ( (Simulator::Now () - m_teleportTime ) < MilliSeconds (50))
+    {
+      return;
+    }
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (txPower, m_expectedPucchTxPower, 0.01, "Wrong Pucch Tx Power");
+}
+
+void
+LteUplinkPowerControlTestCase::SrsTxPowerTrace (uint16_t cellId, uint16_t rnti, double txPower)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("SrsTxPower : CellId: " << cellId << " RNTI: " << rnti << " PuschTxPower: " << txPower);
+  //wait because of RSRP filtering
+  if ( (Simulator::Now () - m_teleportTime ) < MilliSeconds (50))
+    {
+      return;
+    }
+  NS_TEST_ASSERT_MSG_EQ_TOL (txPower, m_expectedSrsTxPower, 0.01, "Wrong Srs Tx Power");
+}
+
+void
+LteUplinkPowerControlTestCase::DoRun (void)
+{
+}
+
+
+LteUplinkOpenLoopPowerControlTestCase::LteUplinkOpenLoopPowerControlTestCase (std::string name)
+  : LteUplinkPowerControlTestCase ("Uplink Open Loop Power Control: " + name)
+{
+  NS_LOG_INFO ("Creating LteUplinkPowerControlTestCase");
+}
+
+LteUplinkOpenLoopPowerControlTestCase::~LteUplinkOpenLoopPowerControlTestCase ()
+{
+}
+
+void
+LteUplinkOpenLoopPowerControlTestCase::DoRun (void)
+{
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (false));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteUePowerControl::PoNominalPusch", IntegerValue (-90));
+  Config::SetDefault ("ns3::LteUePowerControl::PsrsOffset", IntegerValue (9));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+
+  uint8_t bandwidth = 25;
+  double d1 = 0;
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes;
+  enbNodes.Create (1);
+  ueNodes.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes);
+
+/*   the topology is the following:
+ *
+ *   eNB1-------------------------UE
+ *                  d1
+ */
+
+  // Install Mobility Model
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));                  // eNB1
+  positionAlloc->Add (Vector (d1, 0.0, 0.0));           // UE1
+
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+  m_ueMobility = ueNodes.Get (0)->GetObject<MobilityModel> ();
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
+
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  Ptr<LteUePhy> uePhy = DynamicCast<LteUePhy>( ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy () );
+  m_ueUpc = uePhy->GetUplinkPowerControl ();
+
+  m_ueUpc->TraceConnectWithoutContext ("ReportPuschTxPower",
+                                       MakeBoundCallback (&PuschTxPowerNofitication, this));
+  m_ueUpc->TraceConnectWithoutContext ("ReportPucchTxPower",
+                                       MakeBoundCallback (&PucchTxPowerNofitication, this));
+  m_ueUpc->TraceConnectWithoutContext ("ReportSrsTxPower",
+                                       MakeBoundCallback (&SrsTxPowerNofitication, this));
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+  // Activate a data radio bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+
+  //Changing UE position
+  Simulator::Schedule (MilliSeconds (0),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 0, 0, -40, -40, -40);
+  Simulator::Schedule (MilliSeconds (200),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 200, 0, 8.9745, 8.9745, 11.9745);
+  Simulator::Schedule (MilliSeconds (300),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 400, 0, 14.9951, 14.9951, 17.9951 );
+  Simulator::Schedule (MilliSeconds (400),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 600, 0, 18.5169, 18.5169, 21.5169 );
+  Simulator::Schedule (MilliSeconds (500),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 800, 0, 21.0157, 21.0157, 23 );
+  Simulator::Schedule (MilliSeconds (600),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 1000, 0, 22.9539, 22.9539, 23 );
+  Simulator::Schedule (MilliSeconds (700),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 1200, 0, 23, 10, 23 );
+  Simulator::Schedule (MilliSeconds (800),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 400, 0, 14.9951, 14.9951, 17.9951 );
+  Simulator::Schedule (MilliSeconds (900),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 800, 0, 21.0157, 21.0157, 23 );
+  Simulator::Schedule (MilliSeconds (1000),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 0, 0, -40, -40, -40 );
+  Simulator::Schedule (MilliSeconds (1100),
+                       &LteUplinkPowerControlTestCase::TeleportUe, this, 100, 0, 2.9539, 2.9539, 5.9539 );
+  Simulator::Stop (Seconds (1.200));
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+}
+
+LteUplinkClosedLoopPowerControlAbsoluteModeTestCase::LteUplinkClosedLoopPowerControlAbsoluteModeTestCase (std::string name)
+  : LteUplinkPowerControlTestCase ("Uplink Closed Loop Power Control: " + name)
+{
+  NS_LOG_INFO ("Creating LteUplinkClosedLoopPowerControlAbsoluteModeTestCase");
+}
+
+LteUplinkClosedLoopPowerControlAbsoluteModeTestCase::~LteUplinkClosedLoopPowerControlAbsoluteModeTestCase ()
+{
+}
+
+void
+LteUplinkClosedLoopPowerControlAbsoluteModeTestCase::DoRun (void)
+{
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteUePowerControl::PoNominalPusch", IntegerValue (-90));
+  Config::SetDefault ("ns3::LteUePowerControl::PsrsOffset", IntegerValue (9));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFfrSimple");
+
+  uint8_t bandwidth = 25;
+  double d1 = 100;
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes;
+  enbNodes.Create (1);
+  ueNodes.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes);
+
+/*   the topology is the following:
+ *
+ *   eNB1-------------------------UE
+ *                  d1
+ */
+
+  // Install Mobility Model
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));                  // eNB1
+  positionAlloc->Add (Vector (d1, 0.0, 0.0));           // UE1
+
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+  m_ueMobility = ueNodes.Get (0)->GetObject<MobilityModel> ();
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
+
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  Ptr<LteUePhy> uePhy = DynamicCast<LteUePhy>( ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy () );
+  m_ueUpc = uePhy->GetUplinkPowerControl ();
+
+  m_ueUpc->TraceConnectWithoutContext ("ReportPuschTxPower",
+                                       MakeBoundCallback (&PuschTxPowerNofitication, this));
+  m_ueUpc->TraceConnectWithoutContext ("ReportPucchTxPower",
+                                       MakeBoundCallback (&PucchTxPowerNofitication, this));
+  m_ueUpc->TraceConnectWithoutContext ("ReportSrsTxPower",
+                                       MakeBoundCallback (&SrsTxPowerNofitication, this));
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+  // Activate a data radio bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+
+  PointerValue tmp;
+  enbDevs.Get (0)->GetAttribute ("LteFfrAlgorithm", tmp);
+  m_ffrSimple = DynamicCast<LteFfrSimple>(tmp.GetObject ());
+  m_accumulatedMode = false;
+
+  //Changing TPC value
+  Simulator::Schedule (MilliSeconds (0),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 1, 0, 1.9539, 1.9539, 4.9539);
+  Simulator::Schedule (MilliSeconds (100),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 0, 0, -1.0461, -1.0461, 1.9539);
+  Simulator::Schedule (MilliSeconds (200),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 2, 0, 3.9539, 3.9539, 6.9539);
+  Simulator::Schedule (MilliSeconds (300),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 3, 0, 6.9539, 6.9539, 9.9539);
+  Simulator::Schedule (MilliSeconds (400),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 0, 0, -1.0461, -1.0461, 1.9539);
+  Simulator::Schedule (MilliSeconds (500),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 1, 0, 1.9539, 1.9539, 4.9539);
+  Simulator::Schedule (MilliSeconds (600),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 3, 0, 6.9539, 6.9539, 9.9539);
+  Simulator::Schedule (MilliSeconds (800),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 2, 0, 3.9539, 3.9539, 6.9539);
+  Simulator::Stop (Seconds (1.000));
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+}
+
+LteUplinkClosedLoopPowerControlAccumulatedModeTestCase::LteUplinkClosedLoopPowerControlAccumulatedModeTestCase (std::string name)
+  : LteUplinkPowerControlTestCase ("Uplink Closed Loop Power Control: " + name)
+{
+  NS_LOG_INFO ("Creating LteUplinkClosedLoopPowerControlAccumulatedModeTestCase");
+}
+
+LteUplinkClosedLoopPowerControlAccumulatedModeTestCase::~LteUplinkClosedLoopPowerControlAccumulatedModeTestCase ()
+{
+}
+
+void
+LteUplinkClosedLoopPowerControlAccumulatedModeTestCase::DoRun (void)
+{
+  Config::Reset ();
+  Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
+
+  double eNbTxPower = 30;
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (eNbTxPower));
+  Config::SetDefault ("ns3::LteUePhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
+
+  Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (true));
+  Config::SetDefault ("ns3::LteUePowerControl::PoNominalPusch", IntegerValue (-90));
+  Config::SetDefault ("ns3::LteUePowerControl::PsrsOffset", IntegerValue (9));
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetFfrAlgorithmType ("ns3::LteFfrSimple");
+
+  uint8_t bandwidth = 25;
+  double d1 = 10;
+
+  // Create Nodes: eNodeB and UE
+  NodeContainer enbNodes;
+  NodeContainer ueNodes;
+  enbNodes.Create (1);
+  ueNodes.Create (1);
+  NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes);
+
+/*   the topology is the following:
+ *
+ *   eNB1-------------------------UE
+ *                  d1
+ */
+
+  // Install Mobility Model
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));                  // eNB1
+  positionAlloc->Add (Vector (d1, 0.0, 0.0));           // UE1
+
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (allNodes);
+  m_ueMobility = ueNodes.Get (0)->GetObject<MobilityModel> ();
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
+
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
+
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  Ptr<LteUePhy> uePhy = DynamicCast<LteUePhy>( ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy () );
+  m_ueUpc = uePhy->GetUplinkPowerControl ();
+
+  m_ueUpc->TraceConnectWithoutContext ("ReportPuschTxPower",
+                                       MakeBoundCallback (&PuschTxPowerNofitication, this));
+  m_ueUpc->TraceConnectWithoutContext ("ReportPucchTxPower",
+                                       MakeBoundCallback (&PucchTxPowerNofitication, this));
+  m_ueUpc->TraceConnectWithoutContext ("ReportSrsTxPower",
+                                       MakeBoundCallback (&SrsTxPowerNofitication, this));
+
+  // Attach a UE to a eNB
+  lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+  // Activate a data radio bearer
+  enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+  EpsBearer bearer (q);
+  lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+
+  PointerValue tmp;
+  enbDevs.Get (0)->GetAttribute ("LteFfrAlgorithm", tmp);
+  m_ffrSimple = DynamicCast<LteFfrSimple>(tmp.GetObject ());
+  m_accumulatedMode = true;
+
+  //Changing TPC value
+  Simulator::Schedule (MilliSeconds (0),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 1, 0, -17.0461, -17.0461, -14.0461);
+  Simulator::Schedule (MilliSeconds (100),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 0, 20, -37.0461, -37.0461, -34.0461);
+  Simulator::Schedule (MilliSeconds (200),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 0, 20, -40, 10, -37.0461);
+  Simulator::Schedule (MilliSeconds (300),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 2, 1, -39.0461, -39.0461, -36.0461);
+  Simulator::Schedule (MilliSeconds (400),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 3, 10, -9.0461, -9.0461, -6.0461);
+  Simulator::Schedule (MilliSeconds (500),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 2, 15, 5.9539, 5.9539, 8.9539);
+  Simulator::Schedule (MilliSeconds (600),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 3, 1, 8.9539, 8.9539, 11.9539);
+  Simulator::Schedule (MilliSeconds (700),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 2, 10, 18.9539, 18.9539, 21.9539);
+  Simulator::Schedule (MilliSeconds (800),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 2, 20, 23, 23, 23);
+  Simulator::Schedule (MilliSeconds (900),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 0, 1, 22.9539, 22.9539, 23);
+  Simulator::Schedule (MilliSeconds (1000),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 0, 20, 2.9539, 2.9539, 5.9539);
+  Simulator::Schedule (MilliSeconds (1100),
+                       &LteUplinkPowerControlTestCase::SetTpcConfiguration, this, 2, 5, 7.9539, 7.9539, 10.9539);
+  Simulator::Stop (Seconds (1.200));
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-uplink-power-control.h	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,102 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Piotr Gawlowicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
+ *
+ */
+
+#ifndef LTE_TEST_UPLINK_POWER_CONTROL_H
+#define LTE_TEST_UPLINK_POWER_CONTROL_H
+
+#include "ns3/spectrum-value.h"
+#include "ns3/spectrum-test.h"
+#include "ns3/test.h"
+
+using namespace ns3;
+
+/**
+ * Test 1.1 Uplink Power Control
+ */
+class LteUplinkPowerControlTestSuite : public TestSuite
+{
+public:
+  LteUplinkPowerControlTestSuite ();
+};
+
+class LteUplinkPowerControlTestCase : public TestCase
+{
+public:
+  LteUplinkPowerControlTestCase (std::string name);
+  virtual ~LteUplinkPowerControlTestCase ();
+
+  void TeleportUe (uint32_t x, uint32_t y,
+                   double expectedPuschTxPower, double expectedPucchTxPower, double expectedSrsTxPower);
+
+  void SetTpcConfiguration (uint32_t tpc, uint32_t tpcNum,
+                            double expectedPuschTxPower, double expectedPucchTxPower, double expectedSrsTxPower);
+
+  void PuschTxPowerTrace (uint16_t cellId, uint16_t rnti, double txPower);
+  void PucchTxPowerTrace (uint16_t cellId, uint16_t rnti, double txPower);
+  void SrsTxPowerTrace (uint16_t cellId, uint16_t rnti, double txPower);
+
+protected:
+  virtual void DoRun (void);
+
+  Ptr<MobilityModel> m_ueMobility;
+  Time m_teleportTime;
+
+  double m_expectedPuschTxPower;
+  double m_expectedPucchTxPower;
+  double m_expectedSrsTxPower;
+
+  Ptr<LteUePowerControl> m_ueUpc;
+  bool m_accumulatedMode;
+
+  Ptr<LteFfrSimple> m_ffrSimple;
+};
+
+class LteUplinkOpenLoopPowerControlTestCase : public LteUplinkPowerControlTestCase
+{
+public:
+  LteUplinkOpenLoopPowerControlTestCase (std::string name);
+  virtual ~LteUplinkOpenLoopPowerControlTestCase ();
+
+private:
+  virtual void DoRun (void);
+};
+
+class LteUplinkClosedLoopPowerControlAbsoluteModeTestCase : public LteUplinkPowerControlTestCase
+{
+public:
+  LteUplinkClosedLoopPowerControlAbsoluteModeTestCase (std::string name);
+  virtual ~LteUplinkClosedLoopPowerControlAbsoluteModeTestCase ();
+
+private:
+  virtual void DoRun (void);
+};
+
+class LteUplinkClosedLoopPowerControlAccumulatedModeTestCase : public LteUplinkPowerControlTestCase
+{
+public:
+  LteUplinkClosedLoopPowerControlAccumulatedModeTestCase (std::string name);
+  virtual ~LteUplinkClosedLoopPowerControlAccumulatedModeTestCase ();
+
+private:
+  virtual void DoRun (void);
+};
+
+#endif /* LTE_TEST_UPLINK_POWER_CONTROL_H */
--- a/src/lte/test/lte-test-uplink-sinr.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/lte-test-uplink-sinr.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -144,7 +144,7 @@
   dlPhy->SetCellId (cellId);
   ulPhy->SetCellId (cellId);
 
-  Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
+  Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> ();
   ulPhy->AddDataSinrChunkProcessor (chunkProcessor);
 
   /**
@@ -296,7 +296,7 @@
   Simulator::Run ();
 
   /**
-   * Check that the values passed to LteSinrChunkProcessor::EvaluateSinrChunk () correspond
+   * Check that the values passed to LteChunkProcessor::EvaluateChunk () correspond
    * to known values which have been calculated offline (with octave) for the generated signals
    */
   Ptr<SpectrumValue> calculatedSinr = chunkProcessor->GetSinr ();
@@ -345,7 +345,7 @@
   dlPhy->SetCellId (cellId);
   ulPhy->SetCellId (cellId);
   
-  Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
+  Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> ();
   ulPhy->AddCtrlSinrChunkProcessor (chunkProcessor);
   
   /**
@@ -466,7 +466,7 @@
   Simulator::Run ();
   
   /**
-  * Check that the values passed to LteSinrChunkProcessor::EvaluateSinrChunk () correspond
+  * Check that the values passed to LteChunkProcessor::EvaluateChunk () correspond
   * to known values which have been calculated offline (with octave) for the generated signals
   */
   Ptr<SpectrumValue> calculatedSinr = chunkProcessor->GetSinr ();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/reference/lte_cqi_generation.m	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,86 @@
+clear all;
+close all;
+
+%% LTE from theory to practice
+%% Table 22.7 Reference sensitivity.
+
+fdl = 2120e6;  % DL carrier freq Hz, EARFCN = 100
+ful = 1930e6;  % UL carrier freq Hz, EARFCN = 18100 
+
+nrbsControl = 25; % tx bandwidth configuration in number of RBs
+bwControl = nrbsControl * 180000; % bandwidth in Hz, note that this is smaller than
+		    % the nominal Channel Bandwdith, see TS 36.101 fig 5.6-1
+
+nrbsData = 12; % tx bandwidth configuration in number of RBs
+bwData = nrbsData * 180000; % bandwidth in Hz, note that this is smaller than
+		    % the nominal Channel Bandwdith, see TS 36.101 fig 5.6-1
+
+kT = -174; % noise PSD in dBm / Hz
+ndBmData = kT + 10*log10(bwData);  % noise power dBm
+ndBmControl = kT + 10*log10(bwControl);  % noise power dBm
+
+dlpdBm = 30;  % tx power dBm in DL
+dlp = 10.^((dlpdBm - 30)/10); %% tx pow in W in DL
+dlnf = 9; % receiver noise figure in dB in DL
+dlnControl = 10.^((ndBmControl-30+dlnf)/10); %% noise in W in DL
+dlnData = 10.^((ndBmData-30+dlnf)/10); %% noise in W in DL
+
+ulpdBm = 10;  % tx power dBm in UL
+ulp = 10.^((ulpdBm - 30)/10); %% tx pow in W in UL
+ulnf = 5; % receiver noise figure in dB in UL
+uln = 10.^((ndBmControl-30+ulnf)/10); %% noise in W in UL
+
+ber = 0.00005;
+gamma = -log (5*ber)./1.5;
+
+
+%% distances
+%%           d1                   d2  
+%%  eNB1-------------UE1-UE2-----------eNB2
+%%
+
+d1 = 500;
+d2 = 500;
+
+%% propagation gains (linear)
+%%           g11dl             g21dl 
+%%  eNB1-------------UE1-UE2-----------eNB2
+%%           g11ul             g21ul 
+%%              
+
+g11dl = gain_freespace (d1, fdl);
+g11ul = gain_freespace (d1, ful);
+g21dl = gain_freespace (d2, fdl);
+g21ul = gain_freespace (d2, ful);
+
+%% SINR (linear)
+privateRbDlsinr = dlp*g11dl / (dlnControl);
+privateRbUlsinr = ulp*g11ul / (ulp*g21ul + uln); %% new CQI generation approach is only for DL, so in UL CQI is the same
+commonRbDlsinr = dlp*g11dl*24 / (dlp*g21dl*12 + dlnData);
+commonRbUlsinr = ulp*g11ul / (ulp*g21ul + uln);
+
+%% SINR (dB)
+privateRbDlsinrdB = 10.*log10(privateRbDlsinr);
+privateRbUlsinrdB = 10.*log10(privateRbUlsinr);
+commonRbDlsinrdB = 10.*log10(commonRbDlsinr);
+commonRbUlsinrdB = 10.*log10(commonRbUlsinr);
+
+%% Spectal Efficiency
+privateRbDlse = log2(1 + privateRbDlsinr./gamma)
+privateRbUlse = log2(1 + privateRbUlsinr./gamma)
+commonRbDlse = log2(1 + commonRbDlsinr./gamma)
+commonRbUlse = log2(1 + commonRbUlsinr./gamma)
+
+%% to get the MCS, you need to do a manual lookup into 3GPP R1-081483
+%% starting from the spectral efficiency value.
+%% See the Testing section in the LTE module documentation for more info
+%% on how this is done. You might as well look into lte_amc.m
+
+commonRbDlMsc = 4;
+commonRbUlMsc = 2;
+
+privateRbDlMsc = 28;
+privateRbUlMsc = 2; %% new CQI generation approach is only for DL, so in UL CQI is the same
+
+printf("AddTestCase (new LteCqiGenerationTestCase (\"UsePdcchForCqiGeneration\", \"true\", %d, %d , ));\n", commonRbDlMsc, commonRbUlMsc)
+printf("AddTestCase (new LteCqiGenerationTestCase (\"UsePdcchForCqiGeneration\", \"false\", %d, %d , ));\n", privateRbDlMsc, commonRbUlMsc)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/reference/lte_frequency_reuse.m	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,73 @@
+clear all;
+close all;
+
+fdl = 2120e6;  % DL carrier freq Hz, EARFCN = 100
+ful = 1930e6;  % UL carrier freq Hz, EARFCN = 18100 
+nrbs = 25; % tx bandwidth configuration in number of RBs
+dlpdBm = 30;  % tx power dBm in DL, referenceSignalPower
+dlp = 10.^((dlpdBm - 30)/10); %% tx pow in W in DL
+
+
+%%DOWNLINK
+P_A = 0;   %% << change this value to simulate Downlink Power Allocation
+PdschPower = 10.^((dlpdBm+ P_A - 30)/10);
+printf("Expexted Pdsch Power: %f \n", PdschPower)
+
+
+%%UPLINK 
+%% Uplink Power Control Parameters
+Pcmax = 23;
+Pcmin = -40;
+MPusch = 6; %%number of RB used for UL transmission
+PoNominalPusch = -80;
+PoUePusch = 0;
+PsrsOffset = 7;
+alpha = 1;
+deltaTF = 0;
+PoPusch = PoNominalPusch + PoUePusch;
+
+%% Closed Loop Mode
+%% change fc value to simulate closed loop mode
+%%TS36.213 Table 5.1.1.1-2
+%%   TPC   |   Accumulated Mode  |  Absolute Mode
+%%------------------------------------------------
+%%    0    |         -1          |      -4
+%%    1    |          0          |      -1
+%%    2    |          1          |       1
+%%    3    |          3          |       4
+%%------------------------------------------------
+
+
+%% distances
+%%                d1  
+%%  eNB1---------------------UE1
+%%
+d1 = 200;
+fc = -1;
+
+%% different FR schemes have different minimal Uplink sub-bandwidth
+MPusch = 6;
+
+%% pathloss
+%%             pathloss  
+%%  eNB1---------------------UE1
+%%         
+
+pathloss = path_loss (d1, fdl);
+pathlossdB = 10.*log10(pathloss);
+pathlossdB = -pathlossdB;
+
+%% PUSCH TX POWER 
+PuschPowerdB = 10*log10(MPusch) + PoPusch + alpha * pathlossdB + deltaTF + fc;
+
+if (PuschPowerdB > Pcmax)
+  PuschPowerdB = Pcmax;
+endif
+
+if (PuschPowerdB < Pcmin) 
+  PuschPowerdB = Pcmin;
+endif
+
+PuschPower = 10.^((PuschPowerdB - 30 )/10);
+printf("Expexted Pusch Power: %f \n", PuschPower)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/reference/lte_link_budget_interference_fr.m	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,73 @@
+clear all;
+close all;
+
+%% LTE from theory to practice
+%% Table 22.7 Reference sensitivity.
+
+fdl = 2120e6;  % DL carrier freq Hz, EARFCN = 100
+ful = 1930e6;  % UL carrier freq Hz, EARFCN = 18100 
+nrbs = 25; % tx bandwidth configuration in number of RBs
+bw = nrbs * 180000; % bandwidth in Hz, note that this is smaller than
+		    % the nominal Channel Bandwdith, see TS 36.101 fig 5.6-1
+kT = -174; % noise PSD in dBm / Hz
+ndBm = kT + 10*log10(bw);  % noise power dBm
+
+dlpdBm = 30;  % tx power dBm in DL
+dlp = 10.^((dlpdBm - 30)/10); %% tx pow in W in DL
+dlnf = 9; % receiver noise figure in dB in DL
+dln = 10.^((ndBm-30+dlnf)/10); %% noise in W in DL
+
+ulpdBm = 10;  % tx power dBm in UL
+ulp = 10.^((ulpdBm - 30)/10); %% tx pow in W in UL
+ulnf = 5; % receiver noise figure in dB in UL
+uln = 10.^((ndBm-30+ulnf)/10); %% noise in W in UL
+
+ber = 0.00005;
+gamma = -log (5*ber)./1.5;
+
+
+
+%% distances
+%%         d2  
+%%  UE1-----------eNB2
+%%   |             |
+%% d1|             |d1
+%%   |     d2      |
+%%  eNB1----------UE2
+%%
+
+d1 = 50;
+for d2 = [20 50 200 500]
+
+  %% propagation gains (linear)
+  %%             g21dl  
+  %%      UE1<----------eNB2
+  %%      ^ |              
+  %%g11dl1| |g11ul          
+  %%      | v            
+  %%      eNB1<---------UE2
+  %%             g21ul
+
+  g11dl = gain_freespace (d1, fdl);
+  g11ul = gain_freespace (d1, ful);
+  g21dl = gain_freespace (d2, fdl);
+  g21ul = gain_freespace (d2, ful);
+
+  %% SINR (linear)
+  privateRbDlsinr = dlp*g11dl / (dln);
+  privateRbUlsinr = ulp*g11ul / (uln);
+  commonRbDlsinr = dlp*g11dl / (dlp*g21dl + dln);
+  commonRbUlsinr = ulp*g11ul / (ulp*g21ul + uln);
+
+  %% SINR (dB)
+  privateRbDlsinrdB = 10.*log10(privateRbDlsinr);
+  privateRbUlsinrdB = 10.*log10(privateRbUlsinr);
+  commonRbDlsinrdB = 10.*log10(commonRbDlsinr);
+  commonRbUlsinrdB = 10.*log10(commonRbUlsinr);
+
+
+  %%printf("AddTestCase (new LteInterferenceHardFrTestCase (\"d1=%d, d2=%d\", % f, %f, %f, %f , ));\n", d1, d2, d1, d2, privateRbDlsinr, privateRbUlsinr)
+
+  printf("AddTestCase (new LteInterferenceStrictFrTestCase (\"d1=%d, d2=%d\", % f, %f, %f, %f , %f, %f , ));\n", d1, d2, d1, d2, commonRbDlsinr, commonRbUlsinr, privateRbDlsinr, privateRbUlsinr)
+  
+endfor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/reference/lte_uplink_power_control.m	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,135 @@
+clear all;
+close all;
+
+fdl = 2120e6;  % DL carrier freq Hz, EARFCN = 100
+nrbs = 25; % tx bandwidth configuration in number of RBs
+dlpdBm = 30;  % tx power dBm in DL, referenceSignalPower
+dlp = 10.^((dlpdBm - 30)/10); %% tx pow in W in DL ,referenceSignalPower
+
+%% Uplink Power Control Parameters
+Pcmax = 23;
+Pcmin = -40;
+MPusch = 25; %%number of RB used for UL transmission
+PoNominalPusch = -90;
+PoUePusch = 0;
+PsrsOffset = 9;
+alpha = 1;
+deltaTF = 0;
+PoPusch = PoNominalPusch + PoUePusch;
+accumulatedMode = false;
+
+%% Open Loop Power Control
+%%d1 = 1000;
+%%fc = 0;
+
+
+%% Closed Loop Mode
+%% change fc value to simulate closed loop mode
+%%TS36.213 Table 5.1.1.1-2
+%%   TPC   |   Accumulated Mode  |  Absolute Mode
+%%------------------------------------------------
+%%    0    |         -1          |      -4
+%%    1    |          0          |      -1
+%%    2    |          1          |       1
+%%    3    |          3          |       4
+%%------------------------------------------------
+
+%%Absolute Mode 
+d1 = 100;
+fc = -4;
+
+
+%%Accumulated Mode, steps to simulate fc current value
+%%d1 = 10;
+%%fc = 0;
+%%accumulatedMode = true;
+
+stepNumToExecute = 12;
+fcValueSequence = [
+		[0, 0]; 
+		[-1, 20]; 
+		[-1, 20];
+		[1, 1];
+		[3, 10];
+		[1, 15];
+		[3, 1];
+		[1, 10];
+		[1, 10];
+		[-1, 1];
+		[-1, 20];
+		[1, 5]
+                ];
+
+%% distances
+%%                d1  
+%%  eNB1---------------------UE1
+%%
+
+%% pathloss
+%%             pathloss  
+%%  eNB1---------------------UE1
+%%         
+%%
+
+pathloss = path_loss (d1, fdl);
+pathlossdB = 10.*log10(pathloss);
+pathlossdB = -pathlossdB;
+
+%% RSRP (dB)
+rsrqdB = dlpdBm - pathlossdB;
+rsrqdBm = rsrqdB;
+
+if (accumulatedMode) 
+  for i = 1:stepNumToExecute
+    curFcValue = fcValueSequence(i,1);
+    curFcNum = fcValueSequence(i,2);
+
+    for i = 1:curFcNum
+      PuschPower = 10*log10(MPusch) + PoPusch + alpha * pathlossdB + deltaTF + fc;
+      if ((PuschPower > Pcmax && curFcValue> 0) || (PuschPower < Pcmin && curFcValue < 0))
+        %% do not accumulate
+      else
+        fc = fc + curFcValue;
+      endif
+    endfor
+  endfor
+endif
+
+printf("TxPower: %f\n", dlpdBm)
+printf("Distance: %f\n", d1)
+printf("PathLoss: %f \n",pathlossdB)
+printf("RSRP [dBm]: %f \n", rsrqdBm)
+printf("fc: %f \n", fc)
+
+%% PUSCH TX POWER 
+PuschPower = 10*log10(MPusch) + PoPusch + alpha * pathlossdB + deltaTF + fc;
+
+if (PuschPower > Pcmax)
+  PuschPower = Pcmax;
+endif
+
+if (PuschPower < Pcmin) 
+  PuschPower = Pcmin;
+endif
+
+printf("PuschPower: %f \n", PuschPower)
+
+
+%% PUCCH TX POWER 
+PucchPower = PuschPower;
+printf("PucchPower: %f \n", PucchPower)
+
+
+%% SRS TX POWER 
+PsrsOffsetValue = -10.5 + PsrsOffset * 1.5;
+SrsPower = PsrsOffsetValue + 10*log10(nrbs) + PoPusch + alpha * pathlossdB + fc;
+
+if (SrsPower > Pcmax)
+  SrsPower = Pcmax;
+endif
+
+if (SrsPower < Pcmin) 
+  SrsPower = Pcmin;
+endif
+printf("SrsPower: %f \n", SrsPower)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/reference/path_loss.m	Fri Sep 05 01:12:55 2014 +0200
@@ -0,0 +1,18 @@
+function g = path_loss(d, f)
+
+  %%
+  %% function g = path_loss(d, c)
+  %%
+  %% returns the path-loss at d meters for channel c
+  
+  assert(isscalar(f));
+  assert(f > 0);
+
+  g = zeros(size(d));
+  c = 299792458.0;
+  g(find(d > 0)) = (c./(4.0.*pi.*f.*d(find(d > 0)))).^2;
+
+  g(find(d <= 0)) = 1;
+  
+       
+  
--- a/src/lte/test/test-asn1-encoding.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/test-asn1-encoding.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -150,6 +150,9 @@
   physicalConfigDedicated.haveAntennaInfoDedicated = true;
   physicalConfigDedicated.antennaInfo.transmissionMode = 2;
 
+  physicalConfigDedicated.havePdschConfigDedicated = true;
+  physicalConfigDedicated.pdschConfigDedicated.pa = LteRrcSap::PdschConfigDedicated::dB0;
+
   rrd.physicalConfigDedicated = physicalConfigDedicated;
 
   return rrd;
@@ -236,6 +239,17 @@
                                  rrcd2.physicalConfigDedicated.antennaInfo.transmissionMode,
                                  "antennaInfo.transmissionMode");
         }
+
+      NS_TEST_ASSERT_MSG_EQ (rrcd1.physicalConfigDedicated.havePdschConfigDedicated,
+                             rrcd2.physicalConfigDedicated.havePdschConfigDedicated,
+                             "havePdschConfigDedicated");
+
+      if (rrcd1.physicalConfigDedicated.havePdschConfigDedicated)
+        {
+          NS_TEST_ASSERT_MSG_EQ (rrcd1.physicalConfigDedicated.pdschConfigDedicated.pa,
+                                 rrcd2.physicalConfigDedicated.pdschConfigDedicated.pa,
+                                 "pdschConfigDedicated.pa");
+        }
     }
 }
 
--- a/src/lte/test/test-lte-antenna.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/test-lte-antenna.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -99,6 +99,10 @@
   Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
   Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
+
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
 
   // use 0dB Pathloss, since we are testing only the antenna gain
@@ -145,11 +149,11 @@
   // Use testing chunk processor in the PHY layer
   // It will be used to test that the SNR is as intended
   Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testDlSinr = Create<LteTestSinrChunkProcessor> (uePhy);
+  Ptr<LteTestSinrChunkProcessor> testDlSinr = Create<LteTestSinrChunkProcessor> ();
   uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr);
 
   Ptr<LtePhy> enbphy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
-  Ptr<LteTestSinrChunkProcessor> testUlSinr = Create<LteTestSinrChunkProcessor> (enbphy);
+  Ptr<LteTestSinrChunkProcessor> testUlSinr = Create<LteTestSinrChunkProcessor> ();
   enbphy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr);
 
 
--- a/src/lte/test/test-lte-x2-handover-measures.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/test-lte-x2-handover-measures.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -197,6 +197,8 @@
   Config::SetDefault ("ns3::LteEnbRrc::HandoverJoiningTimeoutDuration", TimeValue (MilliSeconds (200)));
   Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (20));
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
 
   int64_t stream = 1;
 
--- a/src/lte/test/test-lte-x2-handover.cc	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/test/test-lte-x2-handover.cc	Fri Sep 05 01:12:55 2014 +0200
@@ -151,6 +151,9 @@
   Config::SetDefault ("ns3::UdpClient::MaxPackets", UintegerValue (1000000));  
   Config::SetDefault ("ns3::UdpClient::PacketSize", UintegerValue (m_udpClientPktSize));  
 
+  //Disable Uplink Power Control
+  Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
+
   int64_t stream = 1;
   
   m_lteHelper = CreateObject<LteHelper> ();
--- a/src/lte/wscript	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/lte/wscript	Fri Sep 05 01:12:55 2014 +0200
@@ -69,7 +69,7 @@
         'model/lte-ue-phy-sap.cc',
         'model/lte-ue-cphy-sap.cc',
         'model/lte-interference.cc',
-        'model/lte-sinr-chunk-processor.cc',
+        'model/lte-chunk-processor.cc',
         'model/pf-ff-mac-scheduler.cc',
         'model/fdmt-ff-mac-scheduler.cc',
         'model/tdmt-ff-mac-scheduler.cc',
@@ -107,6 +107,17 @@
         'model/no-op-handover-algorithm.cc',
         'model/lte-anr-sap.cc',
         'model/lte-anr.cc',
+        'model/lte-ffr-algorithm.cc',
+        'model/lte-ffr-sap.cc',
+        'model/lte-ffr-rrc-sap.cc',
+        'model/lte-fr-no-op-algorithm.cc',
+        'model/lte-fr-hard-algorithm.cc',
+        'model/lte-fr-strict-algorithm.cc',
+        'model/lte-fr-soft-algorithm.cc',
+        'model/lte-ffr-soft-algorithm.cc',
+        'model/lte-ffr-enhanced-algorithm.cc',
+        'model/lte-ffr-distributed-algorithm.cc',
+        'model/lte-ue-power-control.cc',
         ]
 
     module_test = bld.create_ns3_module_test_library('lte')
@@ -155,6 +166,13 @@
         'test/lte-test-cell-selection.cc',
         'test/test-lte-handover-delay.cc',
         'test/test-lte-handover-target.cc',
+        'test/lte-ffr-simple.cc',
+        'test/lte-test-downlink-power-control.cc',
+        'test/lte-test-uplink-power-control.cc',
+        'test/lte-test-frequency-reuse.cc',
+        'test/lte-test-interference-fr.cc',
+        'test/lte-test-cqi-generation.cc',
+        'test/lte-simple-spectrum-phy.cc',
         ]
 
     headers = bld(features='ns3header')
@@ -225,7 +243,7 @@
         'model/lte-ue-phy-sap.h',
         'model/lte-ue-cphy-sap.h',
         'model/lte-interference.h',
-        'model/lte-sinr-chunk-processor.h',
+        'model/lte-chunk-processor.h',
         'model/pf-ff-mac-scheduler.h',
         'model/fdmt-ff-mac-scheduler.h',
         'model/tdmt-ff-mac-scheduler.h',
@@ -263,6 +281,17 @@
         'model/no-op-handover-algorithm.h',
         'model/lte-anr-sap.h',
         'model/lte-anr.h',
+        'model/lte-ffr-algorithm.h',
+        'model/lte-ffr-sap.h',
+        'model/lte-ffr-rrc-sap.h',
+        'model/lte-fr-no-op-algorithm.h',
+        'model/lte-fr-hard-algorithm.h',
+        'model/lte-fr-strict-algorithm.h',
+        'model/lte-fr-soft-algorithm.h',
+        'model/lte-ffr-soft-algorithm.h',
+        'model/lte-ffr-enhanced-algorithm.h',
+        'model/lte-ffr-distributed-algorithm.h',     
+		'model/lte-ue-power-control.h',           
         ]
 
     if (bld.env['ENABLE_EMU']):
--- a/src/spectrum/doc/spectrum.rst	Thu Sep 04 23:13:41 2014 +0300
+++ b/src/spectrum/doc/spectrum.rst	Fri Sep 05 01:12:55 2014 +0200
@@ -20,7 +20,7 @@
 The Spectrum module aims at providing support for modeling the frequency-dependent 
 aspects of communications in |ns3|. 
 The model was first introduced in
-[Baldo2009]_, and has been enhanced and refined over the years. 
+[Baldo2009Spectrum]_, and has been enhanced and refined over the years. 
 
 
 
@@ -84,7 +84,7 @@
 one ``SpectrumModel`` to another.
 
 For a more formal mathematical description of the signal model just
-described, the reader is referred to [Baldo2009]_.
+described, the reader is referred to [Baldo2009Spectrum]_.
 
 The ``SpectrumSignalParameters`` class is meant to include only
 information that is valid for all signals; as such, it is not meant to
@@ -168,7 +168,7 @@
  * ``HalfDuplexIdealPhy``: a basic PHY model using a gaussian
    interference model (implemented in ``SpectrumInterference``)
    together with an error model based on Shannon capacity (described
-   in [Baldo2009]_ and implemented in ``SpectrumErrorModel``. This PHY
+   in [Baldo2009Spectrum]_ and implemented in ``SpectrumErrorModel``. This PHY
    uses the ``GenericPhy`` interface. Its addditional custom signal
    parameters are defined in ``HalfDuplexIdealPhySignalParameters``.
 
@@ -194,7 +194,7 @@
 References
 ==========
 
-.. [Baldo2009] N. Baldo and M. Miozzo, "Spectrum-aware Channel and PHY layer modeling for ns3", 
+.. [Baldo2009Spectrum] N. Baldo and M. Miozzo, "Spectrum-aware Channel and PHY layer modeling for ns3", 
    Proceedings of ICST NSTools 2009, Pisa, Italy
 
 
@@ -275,8 +275,7 @@
 
 
 The helpers provided in ``src/spectrum/helpers`` are mainly intended
-for the example implementations described in :ref:`Example model
-implementations`. 
+for the example implementations described in :ref:`sec-example-model-implementations`. 
 If you are developing your custom model based on the
 spectrum framework, you will probably prefer to define your own
 helpers.