Added UAN package
authorMitch Watrous <watrous@u.washington.edu>
Tue, 26 Oct 2010 08:41:33 -0700
changeset 6622 66d4eab148ce
parent 6621 b30587eaf9e6
child 6623 80d732f733ce
Added UAN package
packages/uan/doc/uan.h
packages/uan/examples/Makefile
packages/uan/examples/uan-cw-example.cc
packages/uan/examples/uan-cw-example.h
packages/uan/examples/uan-rc-example.cc
packages/uan/examples/uan-rc-example.h
packages/uan/examples/wscript
packages/uan/helper/Makefile
packages/uan/helper/uan-helper.cc
packages/uan/helper/uan-helper.h
packages/uan/model/Makefile
packages/uan/model/uan-address.cc
packages/uan/model/uan-address.h
packages/uan/model/uan-channel.cc
packages/uan/model/uan-channel.h
packages/uan/model/uan-header-common.cc
packages/uan/model/uan-header-common.h
packages/uan/model/uan-header-rc.cc
packages/uan/model/uan-header-rc.h
packages/uan/model/uan-mac-aloha.cc
packages/uan/model/uan-mac-aloha.h
packages/uan/model/uan-mac-cw.cc
packages/uan/model/uan-mac-cw.h
packages/uan/model/uan-mac-rc-gw.cc
packages/uan/model/uan-mac-rc-gw.h
packages/uan/model/uan-mac-rc.cc
packages/uan/model/uan-mac-rc.h
packages/uan/model/uan-mac.h
packages/uan/model/uan-module.h
packages/uan/model/uan-net-device.cc
packages/uan/model/uan-net-device.h
packages/uan/model/uan-noise-model-default.cc
packages/uan/model/uan-noise-model-default.h
packages/uan/model/uan-noise-model.cc
packages/uan/model/uan-noise-model.h
packages/uan/model/uan-phy-dual.cc
packages/uan/model/uan-phy-dual.h
packages/uan/model/uan-phy-gen.cc
packages/uan/model/uan-phy-gen.h
packages/uan/model/uan-phy.cc
packages/uan/model/uan-phy.h
packages/uan/model/uan-prop-model-ideal.cc
packages/uan/model/uan-prop-model-ideal.h
packages/uan/model/uan-prop-model-thorp.cc
packages/uan/model/uan-prop-model-thorp.h
packages/uan/model/uan-prop-model.cc
packages/uan/model/uan-prop-model.h
packages/uan/model/uan-transducer-hd.cc
packages/uan/model/uan-transducer-hd.h
packages/uan/model/uan-transducer.h
packages/uan/model/uan-tx-mode.cc
packages/uan/model/uan-tx-mode.h
packages/uan/test/uan-test.cc
packages/uan/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/doc/uan.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,182 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+/**
+ * \ingroup devices
+ * \defgroup UAN UAN Models
+ *
+ * \section UanOverview UAN Module Overview
+ *
+ * The main goal of the UAN Model is to enable researchers to
+ * model a variety of underwater network scenarios.  The UAN model
+ * is broken into three main parts:  The channel, PHY,  and MAC models.
+ *
+ *
+ * \section UanPropOverview UAN Propagation Models
+ *
+ * Modelling of the underwater acoustic channel has been an active
+ * area of research for quite some time.  Given the complications involved,
+ * surface and bottom interactions, varying speed of sound, etc..., the detailed
+ * models in use for ocean acoustics research are much too complex
+ * (in terms of runtime) for use in network level simulations.  We have
+ * attempted to provide the often used models as well as make an attempt to bridge, in part, the gap between
+ * complicated ocean acoustic models and network level simulation.  The three propagation
+ * models included are the ideal channel model, the Thorp propagation model and
+ * the Bellhop propagation model (Available as an addition).
+ *
+ * All of the Propagation Models follow the same simple interface in ns3::UanPropModel.
+ * The propagation models provide a power delay profile (PDP) and pathloss
+ * information.  The PDP is retrieved using the GetPdp method which returns type UanPdp.
+ * ns3::UanPdp utilises a tapped delay line model for the acoustic channel.
+ * The UanPdp class is a container class for Taps, each tap has a delay and amplitude
+ * member corresponding to the time of arrival (relative to the first tap arrival time)
+ * and amplitude.   The propagation model also provides pathloss between the source
+ * and receiver in dB re 1uPa.  The PDP and pathloss can then be used to find the
+ * received signal power over a duration of time (i.e. received signal power in
+ * a symbol duration and ISI which interferes with neighbouring signals).  Both
+ * UanPropModelIdeal and UanPropModelThorp return a single impulse for a PDP.
+ *
+ *  a) Ideal Channel Model ns3::UanPropModelIdeal
+ *
+ *  The ideal channel model assumes 0 pathloss inside a cylindrical area with bounds
+ *  set by attribute.  The ideal channel model also assumes an impulse PDP.
+ *
+ *  b) Thorp Propagation Model ns3::UanPropModelThorp
+ *
+ *  The Thorp Propagation Model calculates pathloss using the well-known Thorp approximation.
+ *  This model is similar to the underwater channel model implemented in ns2 as described here:
+ *
+ *  Harris, A. F. and Zorzi, M. 2007. Modeling the underwater acoustic channel in ns2. In Proceedings
+ *  of the 2nd international Conference on Performance Evaluation Methodologies and Tools
+ *  (Nantes, France, October 22 - 27, 2007). ValueTools, vol. 321. ICST (Institute for Computer
+ *  Sciences Social-Informatics and Telecommunications Engineering), ICST, Brussels, Belgium, 1-8.
+ *
+ *  The frequency used in calculation however, is the center frequency of the modulation as found from
+ *  ns3::UanTxMode.  The Thorp Propagation Model also assumes an impulse channel response.
+ *
+ *  c) Bellhop Propagation Model ns3::UanPropModelBh (Available as an addition)
+ *
+ *  The Bellhop propagation model reads propagation information from a database.  A configuration
+ *  file describing the location, and resolution of the archived information must be supplied via
+ *  attributes.  We have included a utility, create-dat, which can create these data files using the Bellhop
+ *  Acoustic Ray Tracing software (http://oalib.hlsresearch.com/).
+ *
+ *  The create-dat utility requires a Bellhop installation to run.  Bellhop takes
+ *  environment information about the channel, such as sound speed profile, surface height
+ *  bottom type, water depth, and uses a gaussian ray tracing algorithm to determine
+ *  propagation information.  Arrivals from Bellhop are grouped together into equal length
+ *  taps (the arrivals in a tap duration are coherently summed).  The maximum taps are then
+ *  aligned to take the same position in the PDP.  The create-dat utility averages together
+ *  several runs and then normalizes the average such that the sum of all taps is 1.  The same
+ *  configuration file used to create the data files using create-dat should be passed via
+ *  attribute to the Bellhop Propagation Model.
+ *
+ *  The Bellhop propagation model is available as a patch.  The link address will be
+ *  made available here when it is posted online.  Otherwise email lentracy@gmail.com
+ *  for more information.
+ *
+ *
+ * \section UanPhyOverview UAN PHY Model Overview
+ *
+ * The PHY has been designed to allow for relatively easy extension
+ * to new networking scenarios.  We feel this is important as, to date,
+ * there has been no commonly accepted network level simulation model
+ * for underwater networks.  The lack of commonly accepted network simulation
+ * tools has resulted in a wide array of simulators and models used to report
+ * results in literature.  The lack of standardization makes comparing results
+ * nearly impossible.
+ *
+ * The main component of the PHY Model is the generic
+ * PHY class, ns3::UanPhyGen.  The PHY class's general responsibility
+ * is to handle packet acquisition, error determination, and forwarding of successful
+ * packets up to the MAC layer.  The Generic PHY uses two models for determination
+ * of signal to noise ratio (SINR) and packet error rate (PER).  The
+ * combination of the PER and SINR models determine successful reception
+ * of packets.  The PHY model connects to the channel via a Transducer class.
+ * The Transducer class is responsible for tracking all arriving packets and
+ * departing packets over the duration of the events. How the PHY class and the PER and SINR models
+ * respond to packets is based on the "Mode" of the transmission as described by the ns3::UanTxMode
+ * class.
+ *
+ * When a MAC layer sends down a packet to the PHY for transmission it specifies a "mode number" to
+ * be used for the transmission.  The PHY class accepts, as an attribute, a list of supported modes.  The
+ * mode number corresponds to an index in the supported modes.  The UanTxMode contains simple modulation
+ * information and a unique string id.  The generic PHY class will only acquire arriving packets which
+ * use a mode which is in the supported modes list of the PHY.  The mode along with received signal power,
+ * and other pertinent attributes (e.g. possibly interfering packets and their modes) are passed to the SINR
+ * and PER models for calculation of SINR and probability of error.
+ *
+ * Several simple example PER and SINR models have been created.
+ * a) The PER models
+ *    - Default (simple) PER model (ns3::UanPhyPerGenDefault):  The Default PER model tests the packet against a threshold and
+ *      assumes error (with prob. 1) if the SINR is below the threshold or success if the SINR is above
+ *      the threshold
+ *    - Micromodem FH-FSK PER (ns3::UanPhyPerUmodem).  The FH-FSK PER model calculates probability of error assuming a
+ *      rate 1/2 convolutional code with constraint length 9 and a CRC check capable of correcting
+ *      up to 1 bit error.  This is similar to what is used in the receiver of the WHOI Micromodem.
+ *
+ * b) SINR models
+ * - Default Model (ns3::UanPhyCalcSinrDefault), The default SINR model assumes that all transmitted energy is captured at the receiver
+ *   and that there is no ISI.  Any received signal power from interferes acts as additional
+ *   ambient noise.
+ * - FH-FSK SINR Model (ns3::UanPhyCalcSinrFhFsk), The WHOI Micromodem operating in FH-FSK mode uses a predetermined hopping
+ *   pattern that is shared by all nodes in the network.  We model this by only including signal
+ *   energy receiving within one symbol time (as given by ns3::UanTxMode) in calculating the
+ *   received signal power.  A channel clearing time is given to the FH-FSK SINR model via attribute.
+ *   Any signal energy arriving in adjacent signals (after a symbol time and the clearing time) is
+ *   considered ISI and is treated as additional ambient noise.   Interfering signal arrivals inside
+ *   a symbol time (any symbol time) is also counted as additional ambient noise
+ * - Frequency filtered SINR (ns3::UanPhyCalcSinrDual).  This SINR model calculates SINR in the same manner
+ *   as the default model.  This model however only considers interference if there is an overlap in frequency
+ *   of the arriving packets as determined by UanTxMode.
+ *
+ *  In addition to the generic PHY a dual phy layer is also included (ns3::UanPhyDual).  This wraps two
+ *  generic phy layers together to model a net device which includes two receivers.  This was primarily
+ *  developed for UanMacRc, described in the next section.
+ *
+ *\section UanMAC  UAN MAC Model Overview
+ *
+ * Over the last several years there have been a myriad of underwater MAC proposals
+ * in the literature.  We have included three MAC protocols with this distribution:
+ * a) CW-MAC, a MAC protocol which uses a slotted contention window similar in nature to
+ * the IEEE 802.11 DCF.  Nodes have a constant contention window measured in slot times (configured
+ * via attribute).  If the channel is sensed busy, then nodes backoff by randomly (uniform distribution) choose
+ * a slot to transmit in.  The slot time durations are also configured via attribute.  This MAC was described in
+ *
+ * Parrish N.; Tracy L.; Roy S. Arabshahi P.; and Fox, W.,  System Design Considerations for Undersea Networks:
+ * Link and Multiple Access Protocols , IEEE Journal on Selected Areas in Communications (JSAC), Special
+ * Issue on Underwater Wireless Communications and Networks, Dec. 2008.
+ *
+ * b) RC-MAC (ns3::UanMacRc ns3::UanMacRcGw) a reservation channel protocol which dynamically divides
+ * the available bandwidth into a data channel and a control channel.  This MAC protocol
+ * assumes there is a gateway node which all network traffic is destined for.  The current
+ * implementation assumes a single gateway and a single network neighborhood (a single hop network).
+ * RTS/CTS handshaking is used and time is divided into cycles.  Non-gateway nodes transmit RTS packets
+ * on the control channel in parallel to data packet transmissions which were scheduled in the previous cycle
+ * at the start of a new cycle, the gateway responds on the data channel with a CTS packet which includes
+ * packet transmission times of data packets for received RTS packets in the previous cycle as well as bandwidth
+ * allocation information.  At the end of a cycle ACK packets are transmitted for received data packets.
+ *
+ * When a publication is available it will be cited here.
+ *
+ * c) Simple ALOHA (ns3::UanMacAloha)  Nodes transmit at will.
+ *
+ *
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/examples/Makefile	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,70 @@
+# File:  Makefile
+#
+#
+# Makefile to build UAN example executables.
+#
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+CW_EXECUTABLE_DIR = ..
+CW_EXECUTABLE_NAME = uan-cw-example
+CW_EXECUTABLE_DIR_AND_NAME = $(CW_EXECUTABLE_DIR)/$(CW_EXECUTABLE_NAME)
+RC_EXECUTABLE_DIR = ..
+RC_EXECUTABLE_NAME = uan-rc-example
+RC_EXECUTABLE_DIR_AND_NAME = $(RC_EXECUTABLE_DIR)/$(RC_EXECUTABLE_NAME)
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+UAN_LIBRARY_INCLUDE_DIR = ../model
+UAN_LIBRARY_DIR = ..
+UAN_LIBRARY_NAME = ns3-uan
+UAN_LIBRARY_DIR_AND_NAME = $(UAN_LIBRARY_DIR)/$(UAN_LIBRARY_NAME)
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+UAN_HELPER_LIBRARY_INCLUDE_DIR = ../helper
+UAN_HELPER_LIBRARY_DIR = $(UAN_LIBRARY_DIR)
+UAN_HELPER_LIBRARY_NAME = ns3-uan-helper
+UAN_HELPER_LIBRARY_DIR_AND_NAME = $(UAN_HELPER_LIBRARY_DIR)/$(UAN_HELPER_LIBRARY_NAME)
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+NS3_LIBRARY_INCLUDE_DIR = ../../../build/debug
+NS3_LIBRARY_DIR = ../../../build/debug
+NS3_LIBRARY_NAME = ns3
+
+COMPILER_CXX = g++
+
+# XXX Need to handle both debug and optimized mode.
+CXXFLAGS = -g -I$(UAN_LIBRARY_INCLUDE_DIR) -I$(UAN_HELPER_LIBRARY_INCLUDE_DIR) -I$(NS3_LIBRARY_INCLUDE_DIR)
+LINKFLAGS = -l$(UAN_LIBRARY_NAME) -L$(UAN_LIBRARY_DIR) -l$(UAN_HELPER_LIBRARY_NAME) -L$(UAN_HELPER_LIBRARY_DIR) -l$(NS3_LIBRARY_NAME) -L$(NS3_LIBRARY_DIR)
+
+CW_OBJECTS = uan-cw-example.o
+RC_OBJECTS = uan-rc-example.o
+
+%.o: %.cc
+	$(COMPILER_CXX) -c $(CXXFLAGS) $<
+
+all: cw-example rc-example
+
+cw-example: $(CW_OBJECTS)
+	$(COMPILER_CXX) $(LINKFLAGS) -o $(CW_EXECUTABLE_DIR_AND_NAME) $(CW_OBJECTS)
+
+rc-example: $(RC_OBJECTS)
+	$(COMPILER_CXX) $(LINKFLAGS) -o $(RC_EXECUTABLE_DIR_AND_NAME) $(RC_OBJECTS)
+
+uan-cw-example.o: uan-cw-example.cc uan-cw-example.h
+uan-rc-example.o: uan-rc-example.cc uan-rc-example.h
+
+.PHONY: clean
+clean:
+	rm $(CW_EXECUTABLE_DIR_AND_NAME) $(CW_OBJECTS)
+	rm $(RC_EXECUTABLE_DIR_AND_NAME) $(RC_OBJECTS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/examples/uan-cw-example.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,326 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+
+/**
+ * \file uan-cw-example.cc
+ * \ingroup uan
+ * 
+ * This example showcases the "CW-MAC" described in System Design Considerations for Undersea Networks
+ * article in the IEEE Journal on Selected Areas of Communications 2008 by Nathan Parrish, Leonard Tracy
+ * and Sumit Roy.  The MAC protocol is implemented in the class UanMacCw.  CW-MAC is similar in nature
+ * to the IEEE 802.11 DCF with a constant backoff window.  It requires two parameters to be set,
+ * the slot time and the contention window size.  The contention window size is the backoff window
+ * size in slots, and the slot time is the duration of each slot.  These parameters should be set
+ * according to the overall network size, internode spacing and the number of nodes in the network.
+ * 
+ * This example deploys nodes randomly (according to RNG seed of course) in a finite square region with
+ * the X and Y coordinates of the nodes distributed uniformly.  The CW parameter is varied throughout
+ * the simulation in order to show the variation in throughput with respect to changes in CW.
+ */
+
+#include "uan-module.h"
+#include "uan-cw-example.h"
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/node-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/contrib-module.h"
+#include "ns3/helper-module.h"
+
+#include <fstream>
+
+using namespace ns3;
+using namespace ns3::uan;
+
+NS_LOG_COMPONENT_DEFINE("UanCwExample");
+
+Experiment::Experiment () 
+  : m_numNodes (15),
+    m_dataRate (80),
+    m_depth (70),
+    m_boundary (500),
+    m_packetSize (32),
+    m_bytesTotal (0),
+    m_cwMin (10),
+    m_cwMax (400),
+    m_cwStep (10),
+    m_avgs (3),
+    m_slotTime (Seconds (0.2)),
+    m_simTime (Seconds (1000)),
+    m_gnudatfile ("uan-cw-example.gpl"),
+    m_asciitracefile ("uan-cw-example.asc"),
+    m_bhCfgFile ("uan-apps/dat/default.cfg")
+{
+}
+
+void
+Experiment::ResetData ()
+{
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "  Resetting data");
+  m_throughputs.push_back (m_bytesTotal * 8.0 / m_simTime.GetSeconds ());
+  m_bytesTotal = 0;
+}
+
+void
+Experiment::IncrementCw (uint32_t cw)
+{
+  NS_ASSERT (m_throughputs.size () == m_avgs);
+
+  double avgThroughput = 0.0;
+  for (uint32_t i=0; i<m_avgs; i++)
+    {
+      avgThroughput += m_throughputs[i];
+    }
+  avgThroughput /= m_avgs;
+  m_data.Add (cw, avgThroughput);
+  m_throughputs.clear ();
+
+  Config::Set ("/NodeList/*/DeviceList/*/Mac/CW", UintegerValue (cw + m_cwStep));
+
+  SeedManager::SetRun (SeedManager::GetRun () + 1);
+
+  NS_LOG_DEBUG ("Average for cw=" << cw << " over " << m_avgs << " runs: " << avgThroughput);
+}
+void
+Experiment::UpdatePositions (NodeContainer &nodes)
+{
+
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Updating positions");
+  NodeContainer::Iterator it = nodes.Begin ();
+  UniformVariable uv (0, m_boundary);
+  for (; it != nodes.End (); it++)
+    {
+      Ptr<MobilityModel> mp = (*it)->GetObject<MobilityModel> ();
+      mp->SetPosition (Vector (uv.GetValue (), uv.GetValue (), 70.0));
+    }
+}
+
+void
+Experiment::ReceivePacket (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+
+  while (packet = socket->Recv())
+    {
+      m_bytesTotal += packet->GetSize ();
+    }
+  packet = 0;
+}
+
+Gnuplot2dDataset
+Experiment::Run (UanHelper &uan)
+{
+  uan.SetMac ("ns3::UanMacCw", "CW", UintegerValue (m_cwMin), "SlotTime", TimeValue (m_slotTime));
+  NodeContainer nc = NodeContainer ();
+  NodeContainer sink = NodeContainer ();
+  nc.Create (m_numNodes);
+  sink.Create (1);
+
+  PacketSocketHelper socketHelper;
+  socketHelper.Install (nc);
+  socketHelper.Install (sink);
+
+#ifdef UAN_PROP_BH_INSTALLED
+  Ptr<UanPropModelBh> prop = CreateObjectWithAttributes<UanPropModelBh> ("ConfigFile", StringValue ("exbhconfig.cfg"));
+#else 
+  Ptr<UanPropModelIdeal> prop = CreateObjectWithAttributes<UanPropModelIdeal> ();
+#endif //UAN_PROP_BH_INSTALLED
+  Ptr<UanChannel> channel = CreateObjectWithAttributes<UanChannel> ("PropagationModel", PointerValue (prop));
+
+  //Create net device and nodes with UanHelper
+  NetDeviceContainer devices = uan.Install (nc, channel);
+  NetDeviceContainer sinkdev = uan.Install (sink, channel);
+
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator> ();
+
+  {
+    UniformVariable urv (0, m_boundary);
+    pos->Add (Vector (m_boundary / 2.0, m_boundary / 2.0, m_depth));
+    double rsum = 0;
+
+    double minr = 2 * m_boundary;
+    for (uint32_t i = 0; i < m_numNodes; i++)
+      {
+        double x = urv.GetValue ();
+        double y = urv.GetValue ();
+        double newr = sqrt ((x - m_boundary / 2.0) * (x - m_boundary / 2.0)
+                            + (y - m_boundary / 2.0) * (y - m_boundary / 2.0));
+        rsum += newr;
+        minr = std::min (minr, newr);
+        pos->Add (Vector (x, y, m_depth));
+
+      }
+    NS_LOG_DEBUG ("Mean range from gateway: " << rsum / m_numNodes
+                                              << "    min. range " << minr);
+
+    mobility.SetPositionAllocator (pos);
+    mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+    mobility.Install (sink);
+
+    NS_LOG_DEBUG ("Position of sink: "
+                    << sink.Get (0)->GetObject<MobilityModel> ()->GetPosition ());
+    mobility.Install (nc);
+
+    PacketSocketAddress socket;
+    socket.SetSingleDevice (sinkdev.Get(0)->GetIfIndex ());
+    socket.SetPhysicalAddress (sinkdev.Get(0)->GetAddress ());
+    socket.SetProtocol (0);
+
+    OnOffHelper app ("ns3::PacketSocketFactory", Address (socket));
+    app.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+    app.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+    app.SetAttribute ("DataRate", DataRateValue (m_dataRate));
+    app.SetAttribute ("PacketSize", UintegerValue (m_packetSize));
+
+    ApplicationContainer apps = app.Install (nc);
+    apps.Start (Seconds (0.5));
+    Time nextEvent = Seconds (0.5);
+
+
+    for (uint32_t cw = m_cwMin; cw <= m_cwMax; cw += m_cwStep)
+      {
+
+        for (uint32_t an = 0; an < m_avgs; an++)
+          {
+            nextEvent += m_simTime;
+            Simulator::Schedule (nextEvent, &Experiment::ResetData, this);
+            Simulator::Schedule (nextEvent, &Experiment::UpdatePositions, this, nc);
+          }
+        Simulator::Schedule (nextEvent, &Experiment::IncrementCw, this, cw);
+      }
+    apps.Stop (nextEvent + m_simTime);
+
+    Ptr<Node> sinkNode = sink.Get (0);
+    TypeId psfid = TypeId::LookupByName ("ns3::PacketSocketFactory");
+    if (sinkNode->GetObject<SocketFactory> (psfid) == 0)
+      {
+        Ptr<PacketSocketFactory> psf = CreateObject<PacketSocketFactory> ();
+        sinkNode->AggregateObject (psf);
+      }
+    Ptr<Socket> sinkSocket = Socket::CreateSocket (sinkNode, psfid);
+    sinkSocket->Bind (socket);
+    sinkSocket->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
+
+    m_bytesTotal = 0;
+
+    std::ofstream ascii (m_asciitracefile.c_str ());
+    if (!ascii.is_open ())
+      {
+        NS_FATAL_ERROR ("Could not open ascii trace file: "
+                          << m_asciitracefile);
+      }
+    uan.EnableAsciiAll (ascii);
+
+    Simulator::Run ();
+    sinkNode = 0;
+    sinkSocket = 0;
+    pos = 0;
+    channel = 0;
+    prop = 0;
+    for (uint32_t i=0; i < nc.GetN (); i++)
+      {
+        nc.Get (i) = 0;
+      }
+    for (uint32_t i=0; i < sink.GetN (); i++)
+      {
+       sink.Get (i) = 0;
+      }
+
+    for (uint32_t i=0; i < devices.GetN (); i++)
+      {
+        devices.Get (i) = 0;
+      }
+    for (uint32_t i=0; i < sinkdev.GetN (); i++)
+      {
+        sinkdev.Get (i) = 0;
+      }
+
+    Simulator::Destroy ();
+    return m_data;
+  }
+}
+
+int
+main (int argc, char **argv)
+{
+
+  LogComponentEnable ("UanCwExample", LOG_LEVEL_ALL);
+
+  Experiment exp;
+
+  std::string gnudatfile ("cwexpgnuout.dat");
+  std::string perModel = "ns3::UanPhyPerGenDefault";
+  std::string sinrModel = "ns3::UanPhyCalcSinrDefault";
+
+  CommandLine cmd;
+  cmd.AddValue ("NumNodes", "Number of transmitting nodes", exp.m_numNodes);
+  cmd.AddValue ("Depth", "Depth of transmitting and sink nodes", exp.m_depth);
+  cmd.AddValue ("RegionSize", "Size of boundary in meters", exp.m_boundary);
+  cmd.AddValue ("PacketSize", "Generated packet size in bytes", exp.m_packetSize);
+  cmd.AddValue ("DataRate", "DataRate in bps", exp.m_dataRate);
+  cmd.AddValue ("CwMin", "Min CW to simulate", exp.m_cwMin);
+  cmd.AddValue ("CwMax", "Max CW to simulate", exp.m_cwMax);
+  cmd.AddValue ("SlotTime", "Slot time duration", exp.m_slotTime);
+  cmd.AddValue ("Averages", "Number of topologies to test for each cw point", exp.m_avgs);
+  cmd.AddValue ("GnuFile", "Name for GNU Plot output", exp.m_gnudatfile);
+  cmd.AddValue ("PerModel", "PER model name", perModel);
+  cmd.AddValue ("SinrModel", "SINR model name", sinrModel);
+  cmd.Parse (argc, argv);
+
+  ObjectFactory obf;
+  obf.SetTypeId (perModel);
+  Ptr<UanPhyPer> per = obf.Create<UanPhyPer> ();
+  obf.SetTypeId (sinrModel);
+  Ptr<UanPhyCalcSinr> sinr = obf.Create<UanPhyCalcSinr> ();
+
+  UanHelper uan;
+  UanTxMode mode;
+  mode = UanTxModeFactory::CreateMode (UanTxMode::FSK, exp.m_dataRate,
+                                       exp.m_dataRate, 12000,
+                                       exp.m_dataRate, 2,
+                                       "Default mode");
+  UanModesList myModes;
+  myModes.AppendMode (mode);
+
+  uan.SetPhy ("ns3::UanPhyGen",
+              "PerModel", PointerValue (per),
+              "SinrModel", PointerValue (sinr),
+              "SupportedModes", UanModesListValue (myModes));
+
+  Gnuplot gp;
+  Gnuplot2dDataset ds;
+  ds = exp.Run (uan);
+
+  gp.AddDataset (ds);
+
+  std::ofstream of (exp.m_gnudatfile.c_str ());
+  if (!of.is_open ())
+    {
+      NS_FATAL_ERROR ("Can not open GNU Plot outfile: " << exp.m_gnudatfile);
+    }
+  gp.GenerateOutput (of);
+
+  per = 0;
+  sinr = 0;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/examples/uan-cw-example.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,70 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANCWEXAMPLE_H
+#define UANCWEXAMPLE_H
+
+#include "ns3/common-module.h"
+#include "ns3/node-module.h"
+#include "ns3/contrib-module.h"
+#include "uan-module.h"
+#include "ns3/helper-module.h"
+
+using namespace ns3;
+using namespace ns3::uan;
+
+/**
+ * \class Experiment
+ * \brief Helper class for UAN CW MAC example
+ *
+ */
+class Experiment
+{
+public:
+  Gnuplot2dDataset Run (UanHelper &uan);
+  void ReceivePacket (Ptr<Socket> socket);
+  void UpdatePositions (NodeContainer &nodes);
+  void ResetData ();
+  void IncrementCw (uint32_t cw);
+  uint32_t m_numNodes;
+  uint32_t m_dataRate;
+  double m_depth;
+  double m_boundary;
+  uint32_t m_packetSize;
+  uint32_t m_bytesTotal;
+  uint32_t m_cwMin;
+  uint32_t m_cwMax;
+  uint32_t m_cwStep;
+  uint32_t m_avgs;
+
+  Time m_slotTime;
+  Time m_simTime;
+
+  std::string m_gnudatfile;
+  std::string m_asciitracefile;
+  std::string m_bhCfgFile;
+
+  Gnuplot2dDataset m_data;
+  std::vector<double> m_throughputs;
+
+  Experiment ();
+};
+
+#endif //UANCWEXAMPLE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/examples/uan-rc-example.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,307 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+/**
+ * \file uan-rc-example.cc
+ * \ingroup UAN
+ * This example uses UanMacRc and UanMacRcGw which combined form a system
+ * using what is reffered to as RC-MAC.  Details of RC-MAC will be published
+ * soon.  In brief terms, RC-MAC is a dual channel protocol wherein the
+ * available bandwidth is dynamically divided into two channels,
+ * a reservation channel and a data channel.  The network is assumed
+ * to consist of a single gateway node which services several
+ * non-gateway nodes.
+ * 
+ * Time is divided into cycles.  The non-gateway nodes transmit RTS packets
+ * on the reservation channel in parallel to scheduled data transmissions
+ * (scheduled in the previous cycle), and the gateway stores these requests
+ * for the duration of the cycle.  At the start of the next cycle
+ * the gateway node transmits a CTS which contains packet transmission times
+ * for reserved packets as well as bandwidth allocation information
+ * 
+ * This script deploys a single gateway node (current UanMacRc only supports
+ * a single gateway) in the center of a region and then distributes
+ * non-gateway nodes around the gateway with a uniformly distributed range
+ * between each node and the gateway.
+ * 
+ * The script supports two simulation types.  By default the gateway
+ * dynamically determines the optimal parameter settings and
+ * simulations are run with varying number of nodes (SimMin to SimMax as
+ * set by the command line).  If DoNode=0 is given as a command line option
+ * then the mac parameter "a" (approximate expected number of successful
+ * RTS arrivals per cycle) is varied as the simulation parameter.
+ * 
+ * For questions about this MAC protocol email "lentracy@gmail.com"
+ */
+
+#include "uan-module.h"
+#include "uan-rc-example.h"
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/node-module.h"
+#include "ns3/log.h"
+#include "ns3/config.h"
+#include "ns3/callback.h"
+#include "ns3/contrib-module.h"
+
+#include <fstream>
+
+using namespace ns3;
+using namespace ns3::uan;
+
+NS_LOG_COMPONENT_DEFINE ("UanRcExample");
+
+
+Experiment::Experiment () 
+  : m_simMin (1),
+    m_simMax (1),
+    m_simStep (1),
+    m_numRates (1023),
+    m_totalRate (4096),
+    m_maxRange (3000),
+    m_numNodes (15),
+    m_pktSize (1000),
+    m_doNode (true),
+    m_sifs (Seconds (0.05)),
+    m_simTime (Seconds (5000)),
+    m_gnuplotfile ("uan-rc-example.gpl"),
+    m_bytesTotal (0)
+{ 
+}
+
+void
+Experiment::ReceivePacket (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
+    {
+      m_bytesTotal += packet->GetSize ();
+    }
+}
+
+UanTxMode
+Experiment::CreateMode (uint32_t kass,
+                        uint32_t fc,
+                        bool upperblock,
+                        std::string name)
+{
+
+  std::ostringstream buf;
+  buf << name << " " << kass;
+
+  uint32_t rate = m_totalRate/(m_numRates+1)* (kass);
+  uint32_t bw = kass * m_totalRate / (m_numRates+1);
+  uint32_t fcmode;
+  if(upperblock)
+    fcmode = (m_totalRate - bw)/2 + fc;
+  else
+    fcmode = (uint32_t)((-((double) m_totalRate ) + (double) bw)/2.0 + (double) fc);
+
+
+  uint32_t phyrate = m_totalRate;
+
+  UanTxMode mode;
+  mode = UanTxModeFactory::CreateMode (UanTxMode::OTHER,
+                                       rate,
+                                       phyrate,
+                                       fcmode,
+                                       bw,
+                                       2,
+                                       buf.str());
+  return mode;
+}
+
+//Creates m_numRates different modes each dividing m_totalRate Hz (assumes 1 bit per hz)
+//centered at frequency fc
+void
+Experiment::CreateDualModes (uint32_t fc)
+{
+
+
+  for (uint32_t i=1; i < m_numRates+1; i++)
+    {
+      m_controlModes.AppendMode (CreateMode (i, fc, false, "control "));
+    }
+  for (uint32_t i=m_numRates; i > 0; i--)
+    {
+      m_dataModes.AppendMode (CreateMode (i, fc, true, "data "));
+    }
+}
+
+uint32_t
+Experiment::Run (uint32_t param)
+{
+
+  UanHelper uan;
+  
+  m_bytesTotal=0;
+
+  uint32_t nNodes;
+  uint32_t a;
+  if(m_doNode)
+    {
+      a=0;
+      nNodes = param;
+    }
+  else
+    {
+      nNodes = m_numNodes;
+      a = param;
+    }
+  Time pDelay = Seconds((double) m_maxRange / 1500.0);
+
+  uan.SetPhy ("ns3::UanPhyDual",
+              "SupportedModesPhy1", UanModesListValue (m_dataModes),
+              "SupportedModesPhy2", UanModesListValue (m_controlModes));
+
+  uan.SetMac ("ns3::UanMacRcGw",
+              "NumberOfRates", UintegerValue (m_numRates),
+              "NumberOfNodes", UintegerValue (nNodes),
+              "MaxReservations", UintegerValue (a),
+              "RetryRate", DoubleValue(1/30.0),
+              "SIFS", TimeValue (m_sifs),
+              "MaxPropDelay", TimeValue (pDelay),
+              "FrameSize", UintegerValue (m_pktSize));
+  Ptr<UanChannel> chan = CreateObject<UanChannel>();
+
+  NodeContainer sink;
+  sink.Create(1);
+  NetDeviceContainer sinkDev = uan.Install(sink, chan);
+
+  uan.SetMac ("ns3::UanMacRc",
+              "NumberOfRates", UintegerValue (m_numRates),
+              "MaxPropDelay", TimeValue (pDelay),
+              "RetryRate", DoubleValue(1.0/100.0));
+  NodeContainer nodes;
+  nodes.Create (nNodes);
+  NetDeviceContainer devices = uan.Install (nodes, chan);
+
+  MobilityHelper mobility;
+  uint32_t depth = 70;
+  Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator> ();
+
+  UniformVariable urv (0,m_maxRange);
+  UniformVariable utheta (0, 2.0*M_PI);
+  pos->Add (Vector (m_maxRange, m_maxRange, depth));
+
+  for (uint32_t i=0; i<nNodes; i++)
+    {
+      double theta = utheta.GetValue ();
+      double r = urv.GetValue ();
+
+      double x = m_maxRange + r*std::cos (theta);
+      double y = m_maxRange + r*std::sin (theta);
+
+      pos->Add (Vector (x, y, depth));
+
+    }
+
+  mobility.SetPositionAllocator (pos);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (sink);
+  mobility.Install (nodes);
+
+  PacketSocketHelper pktskth;
+  pktskth.Install (nodes);
+  pktskth.Install (sink);
+
+  PacketSocketAddress socket;
+  socket.SetSingleDevice (sinkDev.Get(0)->GetIfIndex ());
+  socket.SetPhysicalAddress (sinkDev.Get(0)->GetAddress ());
+  socket.SetProtocol (0);
+
+  OnOffHelper app ("ns3::PacketSocketFactory", Address (socket));
+  app.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  app.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  app.SetAttribute ("DataRate", DataRateValue (m_totalRate));
+  app.SetAttribute ("PacketSize", UintegerValue (m_pktSize));
+
+  ApplicationContainer apps = app.Install (nodes);
+
+  apps.Start (Seconds (0.5));
+  apps.Stop (m_simTime + Seconds(0.5));
+
+  Ptr<Node> sinkNode = sink.Get (0);
+  TypeId psfid = TypeId::LookupByName ("ns3::PacketSocketFactory");
+
+  Ptr<Socket> sinkSocket = Socket::CreateSocket(sinkNode, psfid);
+  sinkSocket->Bind(socket);
+  sinkSocket->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
+
+  Simulator::Stop (m_simTime + Seconds(0.6));
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  return m_bytesTotal;
+}
+int
+main(int argc, char *argv[])
+{
+
+  LogComponentEnable ("UanRcExample", LOG_LEVEL_ALL);
+
+  Experiment exp;
+
+  CommandLine cmd;
+  cmd.AddValue ("TotalRate", "Total channel capacity", exp.m_totalRate);
+  cmd.AddValue ("NumberRates", "Number of divided rates ( (NumberRates+1)%TotalRate should be 0)", exp.m_numRates);
+  cmd.AddValue ("MaxRange", "Maximum range between gateway and acoustic node", exp.m_maxRange);
+  cmd.AddValue ("SimMin", "Minimum parameter to test (nodes if DoNode=1, \"a\" param otherwise)", exp.m_simMin);
+  cmd.AddValue ("SimMax", "Maximum parameter to test (nodes if DoNode=1, \"a\" param otherwise)", exp.m_simMax);
+  cmd.AddValue ("SimStep", "Ammount to increment param per trial", exp.m_simStep);
+  cmd.AddValue ("DataFile", "Filename for GnuPlot", exp.m_gnuplotfile);
+  cmd.AddValue ("NumberNodes", "Number of nodes (invalid for doNode=1)", exp.m_numNodes);
+  cmd.AddValue ("SIFS", "SIFS time duration", exp.m_sifs);
+  cmd.AddValue ("PktSize", "Packet size in bytes", exp.m_pktSize);
+  cmd.AddValue ("SimTime", "Simulation time per trial", exp.m_simTime);
+  cmd.AddValue ("DoNode", "1 for do max nodes simulation (invalidates AMin and AMax values)", exp.m_doNode);
+  cmd.Parse (argc, argv);
+
+
+
+  exp.CreateDualModes (12000);
+
+;
+
+  Gnuplot2dDataset ds;
+  for (uint32_t param=exp.m_simMin; param<=exp.m_simMax; param += exp.m_simStep)
+    {
+      uint32_t bytesRx = exp.Run (param);
+      NS_LOG_DEBUG ("param=" << param << ":  Received " << bytesRx << " bytes at sink");
+
+      double util = bytesRx*8.0/(exp.m_simTime.GetSeconds ()*exp.m_totalRate);
+
+      ds.Add (param, util);
+
+      SeedManager::SetRun (SeedManager::GetRun () + 1);
+    }
+
+  Gnuplot gp;
+  gp.AddDataset (ds);
+  std::ofstream of (exp.m_gnuplotfile.c_str ());
+  if (!of.is_open ())
+    {
+      NS_FATAL_ERROR ("Can not open GNU Plot outfile: " << exp.m_gnuplotfile);
+    }
+  gp.GenerateOutput (of);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/examples/uan-rc-example.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,67 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANRCEXAMPLE_H
+#define UANRCEXAMPLE_H
+
+#include "ns3/common-module.h"
+#include "ns3/node-module.h"
+#include "ns3/contrib-module.h"
+#include "ns3/helper-module.h"
+#include "uan-module.h"
+
+using namespace ns3;
+using namespace ns3::uan;
+
+class Experiment
+{
+public:
+  uint32_t m_simMin;
+  uint32_t m_simMax;
+  uint32_t m_simStep;
+  uint32_t m_numRates;
+  uint32_t m_totalRate;
+  uint32_t m_maxRange;
+  uint32_t m_numNodes;
+  uint32_t m_pktSize;
+  bool m_doNode;
+  Time m_sifs;
+  Time m_simTime;
+
+  std::string m_gnuplotfile;
+
+  uint32_t m_bytesTotal;
+
+  UanModesList m_dataModes;
+  UanModesList m_controlModes;
+
+  void ReceivePacket (Ptr<Socket> socket);
+  UanTxMode CreateMode (uint32_t kass,
+                        uint32_t fc,
+                        bool upperblock,
+                        std::string name);
+  void CreateDualModes (uint32_t fc);
+  uint32_t Run (uint32_t param);
+
+  Experiment();
+
+};
+
+#endif //UANRCEXAMPLE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/examples/wscript	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,8 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    obj = bld.create_ns3_program('uan-cw-example', ['core', 'simulator', 'mobility', 'uan'])
+    obj.source = 'uan-cw-example.cc'
+
+    obj = bld.create_ns3_program('uan-rc-example', ['core', 'simulator', 'mobility', 'uan'])
+    obj.source = 'uan-rc-example.cc'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/helper/Makefile	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,52 @@
+# File:  Makefile
+#
+#
+# Makefile to build UAN helper library.
+#
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+UAN_HELPER_LIBRARY_DIR = ..
+UAN_HELPER_LIBRARY_NAME = libns3-uan-helper.so
+UAN_HELPER_LIBRARY_DIR_AND_NAME = $(UAN_HELPER_LIBRARY_DIR)/$(UAN_HELPER_LIBRARY_NAME)
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+UAN_LIBRARY_INCLUDE_DIR = ../model
+UAN_LIBRARY_DIR = ..
+UAN_LIBRARY_NAME = ns3-uan
+UAN_LIBRARY_DIR_AND_NAME = $(UAN_LIBRARY_DIR)/$(UAN_LIBRARY_NAME)
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+NS3_LIBRARY_INCLUDE_DIR = ../../../build/debug
+NS3_LIBRARY_DIR = ../../../build/debug
+NS3_LIBRARY_NAME = ns3
+
+COMPILER_CXX = g++
+
+# XXX Need to handle both debug and optimized mode.
+CXXFLAGS = -fPIC -g -I$(UAN_LIBRARY_INCLUDE_DIR) -I$(NS3_LIBRARY_INCLUDE_DIR)
+LINKFLAGS = -shared  -Wl,-soname,$(UAN_HELPER_LIBRARY_NAME) -l$(UAN_LIBRARY_NAME) -L$(UAN_LIBRARY_DIR) -l$(NS3_LIBRARY_NAME) -L$(NS3_LIBRARY_DIR)
+
+OBJECTS = uan-helper.o
+
+%.o: %.cc
+	$(COMPILER_CXX) -c $(CXXFLAGS) $<
+
+all: library
+
+library: $(OBJECTS)
+	$(COMPILER_CXX) $(LINKFLAGS) -o $(UAN_HELPER_LIBRARY_DIR_AND_NAME) $(OBJECTS)
+
+uan-helper.o: uan-helper.cc uan-helper.h
+
+.PHONY: clean
+clean:
+	rm $(UAN_HELPER_LIBRARY_DIR_AND_NAME) $(OBJECTS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/helper/uan-helper.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,229 @@
+/*
+ * uan-helper.cc
+ *
+ *  Copyright (c) 2008 University of Washington
+ *
+ *  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
+ *
+ *  Created on: 9-Oct-2008
+ *  Author: Leonard Tracy <lentracy@u.washington.edu>
+ *
+ *
+ */
+
+#include "uan-helper.h"
+#include "uan-net-device.h"
+#include "uan-mac.h"
+#include "uan-phy.h"
+#include "uan-channel.h"
+#include "uan-prop-model.h"
+#include "uan-prop-model-ideal.h"
+#include "uan-transducer.h"
+#include "ns3/mobility-model.h"
+#include "ns3/log.h"
+#include "uan-tx-mode.h"
+#include "ns3/config.h"
+#include "ns3/simulator.h"
+#include "uan-noise-model-default.h"
+
+#include <sstream>
+#include <string>
+
+NS_LOG_COMPONENT_DEFINE("UanHelper");
+namespace ns3{
+namespace uan{
+
+static void AsciiPhyTxEvent (std::ostream *os, std::string context,
+    Ptr<const Packet> packet, double txPowerDb, UanTxMode mode)
+{
+  *os << "+ " << Simulator::Now ().GetSeconds () << " " << context << " " << *packet << std::endl;
+}
+
+static void AsciiPhyRxOkEvent (std::ostream *os, std::string context,
+    Ptr<const Packet> packet, double snr, UanTxMode mode)
+{
+  *os << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *packet << std::endl;
+}
+
+UanHelper::UanHelper ()
+{
+  m_mac.SetTypeId ("ns3::UanMacAloha");
+  m_phy.SetTypeId ("ns3::UanPhyGen");
+  m_transducer.SetTypeId ("ns3::UanTransducerHd");
+
+}
+
+UanHelper::~UanHelper ()
+{
+
+}
+
+
+void
+UanHelper::SetMac (std::string macType,
+                   std::string n0, const AttributeValue &v0,
+                   std::string n1, const AttributeValue &v1,
+                   std::string n2, const AttributeValue &v2,
+                   std::string n3, const AttributeValue &v3,
+                   std::string n4, const AttributeValue &v4,
+                   std::string n5, const AttributeValue &v5,
+                   std::string n6, const AttributeValue &v6,
+                   std::string n7, const AttributeValue &v7)
+{
+  m_mac = ObjectFactory ();
+  m_mac.SetTypeId (macType);
+  m_mac.Set (n0, v0);
+  m_mac.Set (n1, v1);
+  m_mac.Set (n2, v2);
+  m_mac.Set (n3, v3);
+  m_mac.Set (n4, v4);
+  m_mac.Set (n5, v5);
+  m_mac.Set (n6, v6);
+  m_mac.Set (n7, v7);
+}
+
+void
+UanHelper::SetPhy (std::string phyType,
+                   std::string n0, const AttributeValue &v0,
+                   std::string n1, const AttributeValue &v1,
+                   std::string n2, const AttributeValue &v2,
+                   std::string n3, const AttributeValue &v3,
+                   std::string n4, const AttributeValue &v4,
+                   std::string n5, const AttributeValue &v5,
+                   std::string n6, const AttributeValue &v6,
+                   std::string n7, const AttributeValue &v7)
+{
+  m_phy = ObjectFactory ();
+  m_phy.SetTypeId (phyType);
+  m_phy.Set (n0, v0);
+  m_phy.Set (n1, v1);
+  m_phy.Set (n2, v2);
+  m_phy.Set (n3, v3);
+  m_phy.Set (n4, v4);
+  m_phy.Set (n5, v5);
+  m_phy.Set (n6, v6);
+  m_phy.Set (n7, v7);
+
+}
+
+void
+UanHelper::SetTransducer (std::string type,
+                          std::string n0, const AttributeValue &v0,
+                          std::string n1, const AttributeValue &v1,
+                          std::string n2, const AttributeValue &v2,
+                          std::string n3, const AttributeValue &v3,
+                          std::string n4, const AttributeValue &v4,
+                          std::string n5, const AttributeValue &v5,
+                          std::string n6, const AttributeValue &v6,
+                          std::string n7, const AttributeValue &v7)
+{
+  m_transducer = ObjectFactory ();
+  m_transducer.SetTypeId (type);
+  m_transducer.Set (n0, v0);
+  m_transducer.Set (n1, v1);
+  m_transducer.Set (n2, v2);
+  m_transducer.Set (n3, v3);
+  m_transducer.Set (n4, v4);
+  m_transducer.Set (n5, v5);
+  m_transducer.Set (n6, v6);
+  m_transducer.Set (n7, v7);
+
+}
+
+void
+UanHelper::EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid)
+{
+  Packet::EnablePrinting ();
+  std::ostringstream oss;
+
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::UanNetDevice/Phy/RxOk";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyRxOkEvent, &os));
+
+  oss.str ("");
+
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::UanNetDevice/Phy/Tx";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyTxEvent, &os));
+}
+
+void
+UanHelper::EnableAscii (std::ostream &os, NetDeviceContainer d)
+{
+  for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i)
+    {
+      Ptr<NetDevice> dev = *i;
+      EnableAscii (os, dev->GetNode ()->GetId (), dev->GetIfIndex ());
+    }
+}
+
+void
+UanHelper::EnableAscii (std::ostream &os, NodeContainer n)
+{
+  NetDeviceContainer devs;
+  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
+    {
+      Ptr<Node> node = *i;
+      for (uint32_t j = 0; j < node->GetNDevices (); ++j)
+        {
+          devs.Add (node->GetDevice (j));
+        }
+    }
+  EnableAscii (os, devs);
+}
+
+void
+UanHelper::EnableAsciiAll (std::ostream &os)
+{
+  EnableAscii (os, NodeContainer::GetGlobal ());
+}
+
+NetDeviceContainer
+UanHelper::Install (NodeContainer c) const
+{
+
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  Ptr<UanNoiseModelDefault> noise =CreateObject<UanNoiseModelDefault> ();
+  channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
+  channel->SetNoiseModel (noise);
+
+  return Install (c, channel);
+}
+
+NetDeviceContainer
+UanHelper::Install (NodeContainer c, Ptr<UanChannel> channel) const
+{
+  NetDeviceContainer devices;
+  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); i++)
+    {
+      Ptr<Node> node = *i;
+      Ptr<UanNetDevice> device = CreateObject<UanNetDevice> ();
+
+      Ptr<UanMac> mac = m_mac.Create<UanMac> ();
+      Ptr<UanPhy> phy = m_phy.Create<UanPhy> ();
+      Ptr<UanTransducer> trans = m_transducer.Create<UanTransducer> ();
+
+      mac->SetAddress (UanAddress::Allocate ());
+      device->SetMac (mac);
+      device->SetPhy (phy);
+      device->SetTransducer(trans);
+      device->SetChannel (channel);
+
+      node->AddDevice (device);
+      devices.Add (device);
+      NS_LOG_DEBUG ("node="<<node<<", mob="<<node->GetObject<MobilityModel> ());
+    }
+  return devices;
+}
+
+} //end namespace uan
+} //end namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/helper/uan-helper.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2008 University of Washington
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Leonard Tracy <lentracy@u.washington.edu>
+ *
+ *
+ */
+
+#ifndef UANHELPER_H_
+#define UANHELPER_H_
+
+#include <string>
+#include "ns3/attribute.h"
+#include "ns3/object-factory.h"
+#include "ns3/node-container.h"
+#include "ns3/net-device-container.h"
+
+namespace ns3{
+namespace uan{
+
+class UanChannel;
+
+class UanHelper
+{
+public:
+  UanHelper();
+  virtual ~UanHelper();
+
+  /**
+   * \param type the type of ns3::UanMac to create.
+   * \param n0 the name of the attribute to set
+   * \param v0 the value of the attribute to set
+   * \param n1 the name of the attribute to set
+   * \param v1 the value of the attribute to set
+   * \param n2 the name of the attribute to set
+   * \param v2 the value of the attribute to set
+   * \param n3 the name of the attribute to set
+   * \param v3 the value of the attribute to set
+   * \param n4 the name of the attribute to set
+   * \param v4 the value of the attribute to set
+   * \param n5 the name of the attribute to set
+   * \param v5 the value of the attribute to set
+   * \param n6 the name of the attribute to set
+   * \param v6 the value of the attribute to set
+   * \param n7 the name of the attribute to set
+   * \param v7 the value of the attribute to set
+   *
+   * All the attributes specified in this method should exist
+   * in the requested mac.
+   */
+  void SetMac (std::string type,
+               std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+               std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+               std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+               std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+               std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+               std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+               std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+               std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+
+
+  /**
+   * \param phyType the type of ns3::UanPhy to create.
+   * \param n0 the name of the attribute to set
+   * \param v0 the value of the attribute to set
+   * \param n1 the name of the attribute to set
+   * \param v1 the value of the attribute to set
+   * \param n2 the name of the attribute to set
+   * \param v2 the value of the attribute to set
+   * \param n3 the name of the attribute to set
+   * \param v3 the value of the attribute to set
+   * \param n4 the name of the attribute to set
+   * \param v4 the value of the attribute to set
+   * \param n5 the name of the attribute to set
+   * \param v5 the value of the attribute to set
+   * \param n6 the name of the attribute to set
+   * \param v6 the value of the attribute to set
+   * \param n7 the name of the attribute to set
+   * \param v7 the value of the attribute to set
+   *
+   * All the attributes specified in this method should exist
+   * in the requested phy.
+   */
+  void SetPhy (std::string phyType,
+               std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+               std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+               std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+               std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+               std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+               std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+               std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+               std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+
+
+  /**
+   * \param type the type of ns3::Transducer to create
+   * \param n0 the name of the attribute to set
+   * \param v0 the value of the attribute to set
+   * \param n1 the name of the attribute to set
+   * \param v1 the value of the attribute to set
+   * \param n2 the name of the attribute to set
+   * \param v2 the value of the attribute to set
+   * \param n3 the name of the attribute to set
+   * \param v3 the value of the attribute to set
+   * \param n4 the name of the attribute to set
+   * \param v4 the value of the attribute to set
+   * \param n5 the name of the attribute to set
+   * \param v5 the value of the attribute to set
+   * \param n6 the name of the attribute to set
+   * \param v6 the value of the attribute to set
+   * \param n7 the name of the attribute to set
+   * \param v7 the value of the attribute to set
+   *
+   * All the attributes specified in this method should exist
+   * in the requested transducer.
+   */
+  void SetTransducer (std::string type,
+               std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+               std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+               std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+               std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+               std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+               std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+               std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+               std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+  /**
+   * \param os output stream
+   * \param nodeid the id of the node to generate ascii output for.
+   * \param deviceid the id of the device to generate ascii output for.
+   *
+   * Enable ascii output on the specified deviceid within the
+   * specified nodeid if it is of type ns3::WifiNetDevice and dump
+   * that to the specified stdc++ output stream.
+   */
+  static void EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid);
+  /**
+   * \param os output stream
+   * \param d device container
+   *
+   * Enable ascii output on each device which is of the
+   * ns3::WifiNetDevice type and which is located in the input
+   * device container and dump that to the specified
+   * stdc++ output stream.
+   */
+  static void EnableAscii (std::ostream &os, NetDeviceContainer d);
+  /**
+   * \param os output stream
+   * \param n node container
+   *
+   * Enable ascii output on each device which is of the
+   * ns3::WifiNetDevice type and which is located in one
+   * of the input node and dump that to the specified
+   * stdc++ output stream.
+   */
+  static void EnableAscii (std::ostream &os, NodeContainer n);
+  /**
+   * \param os output stream
+   *
+   * Enable ascii output on each device which is of the
+   * ns3::WifiNetDevice type and dump that to the specified
+   * stdc++ output stream.
+   */
+  static void EnableAsciiAll (std::ostream &os);
+
+  /**
+   * \param c a set of nodes
+   *
+   * This method creates a simple ns3::WifiChannel (with a default
+   * ns3::PropagationLossModel and ns3::PropagationDelayModel) and
+   * creates, for each of the input nodes, a new ns3::WifiNetDevice
+   * attached to this shared channel. Each ns3::WifiNetDevice is also
+   * configured with an ns3::WifiRemoteStationManager, ns3::WifiMac, and,
+   * ns3::WifiPhy, all of which are created based on the user-specified
+   * attributes specified in WifiHelper::SetRemoteStationManager,
+   * WifiHelper::SetMac, and, WifiHelper::SetPhy.
+   */
+
+  NetDeviceContainer Install (NodeContainer c) const;
+  /**
+   * \param channel a channel to use
+   * \param c a set of nodes
+   *
+   * For each of the input nodes, a new ns3::WifiNetDevice is attached
+   * to the shared input channel. Each ns3::WifiNetDevice is also
+   * configured with an ns3::WifiRemoteStationManager, ns3::WifiMac, and,
+   * ns3::WifiPhy, all of which are created based on the user-specified
+   * attributes specified in WifiHelper::SetRemoteStationManager,
+   * WifiHelper::SetMac, and, WifiHelper::SetPhy.
+   *
+   * The user is expected to attach to the input channel a proper
+   * ns3::PropagationLossModel, and ns3::PropagationDelayModel.
+   */
+  NetDeviceContainer Install (NodeContainer c, Ptr<UanChannel> channel) const;
+
+private:
+  ObjectFactory m_mac;
+  ObjectFactory m_phy;
+  ObjectFactory m_transducer;
+
+};
+
+} //end namespace uan
+} //end namespace ns3
+
+#endif /* UANHELPER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/Makefile	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,79 @@
+# File:  Makefile
+#
+#
+# Makefile to build UAN library.
+#
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+UAN_LIBRARY_DIR = ..
+UAN_LIBRARY_NAME = libns3-uan.so
+UAN_LIBRARY_DIR_AND_NAME = $(UAN_LIBRARY_DIR)/$(UAN_LIBRARY_NAME)
+
+# XXX Put these files in traditional header and library directories
+# rather than using relative paths.
+#
+# XXX Need way to manage multiple builds.
+NS3_LIBRARY_INCLUDE_DIR = ../../../build/debug
+NS3_LIBRARY_DIR = ../../../build/debug
+NS3_LIBRARY_NAME = ns3
+
+COMPILER_CXX = g++
+
+# XXX Need to handle both debug and optimized mode.
+CXXFLAGS = -fPIC -g -I$(NS3_LIBRARY_INCLUDE_DIR)
+LINKFLAGS = -shared -Wl,-soname,$(UAN_LIBRARY_NAME) -l$(NS3_LIBRARY_NAME) -L$(NS3_LIBRARY_DIR)
+
+OBJECTS = uan-address.o \
+          uan-channel.o \
+          uan-header-common.o \
+          uan-header-rc.o \
+          uan-mac-aloha.o \
+          uan-mac-cw.o \
+          uan-mac-rc-gw.o \
+          uan-mac-rc.o \
+          uan-net-device.o \
+          uan-noise-model-default.o \
+          uan-noise-model.o \
+          uan-phy-dual.o \
+          uan-phy-gen.o \
+          uan-phy.o \
+          uan-prop-model.o \
+          uan-prop-model-ideal.o \
+          uan-prop-model-thorp.o \
+          uan-transducer-hd.o \
+          uan-tx-mode.o
+
+%.o: %.cc
+	$(COMPILER_CXX) -c $(CXXFLAGS) $<
+
+all: library
+
+library: $(OBJECTS)
+	$(COMPILER_CXX) $(LINKFLAGS) -o $(UAN_LIBRARY_DIR_AND_NAME) $(OBJECTS)
+
+uan-address.o:             uan-address.cc             uan-address.h
+uan-channel.o:             uan-channel.cc             uan-channel.h
+uan-header-common.o:       uan-header-common.cc       uan-header-common.h
+uan-header-rc.o:           uan-header-rc.cc           uan-header-rc.h
+uan-mac-aloha.o:           uan-mac-aloha.cc           uan-mac-aloha.h
+uan-mac-cw.o:              uan-mac-cw.cc              uan-mac-cw.h
+uan-mac-rc-gw.o:           uan-mac-rc-gw.cc           uan-mac-rc-gw.h
+uan-mac-rc.o:              uan-mac-rc.cc              uan-mac-rc.h
+uan-net-device.o:          uan-net-device.cc          uan-net-device.h
+uan-noise-model-default.o: uan-noise-model-default.cc uan-noise-model-default.h
+uan-noise-model.o:         uan-noise-model.cc         uan-noise-model.h
+uan-phy-dual.o:            uan-phy-dual.cc            uan-phy-dual.h
+uan-phy-gen.o:             uan-phy-gen.cc             uan-phy-gen.h
+uan-phy.o:                 uan-phy.cc                 uan-phy.h
+uan-prop-model.o:          uan-prop-model.cc          uan-prop-model.h
+uan-prop-model-ideal.o:    uan-prop-model-ideal.cc    uan-prop-model-ideal.h
+uan-prop-model-thorp.o:    uan-prop-model-thorp.cc    uan-prop-model-thorp.h
+uan-transducer-hd.o:       uan-transducer-hd.cc       uan-transducer-hd.h
+uan-tx-mode.o:             uan-tx-mode.cc             uan-tx-mode.h
+
+.PHONY: clean
+clean:
+	rm $(UAN_LIBRARY_DIR_AND_NAME) $(OBJECTS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-address.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,141 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-address.h"
+#include "ns3/address.h"
+
+namespace ns3 {
+namespace uan {
+
+UanAddress::UanAddress ()
+{
+  m_address = 255;
+}
+
+UanAddress::UanAddress (uint8_t addr)
+  : m_address (addr)
+{
+}
+
+UanAddress::~UanAddress ()
+{
+}
+
+uint8_t
+UanAddress::GetType (void)
+{
+  static uint8_t type = Address::Register ();
+  return type;
+}
+
+Address
+UanAddress::ConvertTo (void) const
+{
+  return Address (GetType (), &m_address, 1);
+}
+
+UanAddress
+UanAddress::ConvertFrom (const Address &address)
+{
+  NS_ASSERT (IsMatchingType (address));
+  UanAddress uAddr;
+  address.CopyTo (&uAddr.m_address);
+  return uAddr;
+}
+
+uint8_t
+UanAddress::GetAsInt (void) const
+{
+  return m_address;
+}
+bool
+UanAddress::IsMatchingType (const Address &address)
+{
+  return address.CheckCompatible (GetType (), 1);
+}
+
+UanAddress::operator Address () const
+{
+  return ConvertTo ();
+}
+
+void
+UanAddress::CopyFrom (const uint8_t *pBuffer)
+{
+  m_address = *pBuffer;
+}
+
+void
+UanAddress::CopyTo (uint8_t *pBuffer)
+{
+  *pBuffer = m_address;
+
+}
+
+UanAddress
+UanAddress::GetBroadcast ()
+{
+  return UanAddress (255);
+}
+UanAddress
+UanAddress::Allocate ()
+{
+  static uint8_t nextAllocated = 0;
+
+  uint32_t address = nextAllocated++;
+  if (nextAllocated == 255)
+    {
+      nextAllocated = 0;
+    }
+
+  return UanAddress (address);
+}
+
+bool
+operator == (const UanAddress &a, const UanAddress &b)
+{
+  return a.m_address == b.m_address;
+}
+
+bool
+operator != (const UanAddress &a, const UanAddress &b)
+{
+  return !(a == b);
+}
+
+std::ostream&
+operator<< (std::ostream& os, const UanAddress & address)
+{
+  os << (int) address.m_address;
+  return os;
+}
+std::istream&
+operator>> (std::istream& is, UanAddress & address)
+{
+  int x;
+  is >> x;
+  NS_ASSERT (0 <= x);
+  NS_ASSERT (x <= 255);
+  address.m_address = x;
+  return is;
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-address.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,131 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANADDRESS_H
+#define UANADDRESS_H
+
+#include "ns3/address.h"
+#include <iostream>
+
+namespace ns3 {
+namespace uan {
+
+/**
+ * \class UanAddress
+ *
+ * A class used for addressing UAN MAC's.  This implementation uses a simple 8 bit
+ * flat addressing scheme.  It is unlikely that perceived underwater networks will
+ * soon exceed 200 nodes (or the overlapping of two underwater networks - the ocean is big),
+ * so this should provide adequate addressing for most applications.
+ */
+class UanAddress
+{
+public:
+  UanAddress ();
+  /**
+   * \param addr byte address to assign to this address
+   * \brief Create UanAddress object with address addr
+   */
+  UanAddress (uint8_t addr);
+  virtual ~UanAddress ();
+
+  /**
+   * \param address  Address to convert to UAN address
+   * \returns UanAddress from Address
+   */
+  static UanAddress ConvertFrom (const Address &address);
+
+  /**
+   * \param address  Address to test
+   * \returns True if address given is consistant with UanAddress
+   */
+  static bool IsMatchingType  (const Address &address);
+
+  /**
+   * \brief Create UanAddress object with broadcast address
+   */
+  operator Address () const;
+
+  /**
+   * \param pBuffer Buffer to extract address from
+   * \brief Sets address to address stored in parameter
+   */
+  void CopyFrom (const uint8_t *pBuffer);
+
+  /**
+   * \param pBuffer
+   * \brief Writes address to buffer parameter
+   */
+  void CopyTo (uint8_t *pBuffer);
+
+  /**
+   * \returns 8 bit integer version of address
+   */
+  uint8_t GetAsInt (void) const;
+
+  /**
+   * \returns Broadcast address: 255
+   */
+  static UanAddress GetBroadcast (void);
+
+  /**
+   * \brief Allocates UanAddress from 0-254 (will wrap back to 0 if more than 255 are allocated)
+   */
+  static UanAddress Allocate ();
+
+
+private:
+  uint8_t m_address;
+
+  static uint8_t GetType (void);
+  Address ConvertTo (void) const;
+
+  friend bool operator == (const UanAddress &a, const UanAddress &b);
+  friend bool operator != (const UanAddress &a, const UanAddress &b);
+  friend std::ostream& operator<< (std::ostream& os, const UanAddress & address);
+  friend std::istream& operator>> (std::istream& is, UanAddress & address);
+
+};
+
+
+/**
+ * \brief Returns true if byte address a is equal to byte address b
+ */
+bool operator == (const UanAddress &a, const UanAddress &b);
+
+/**
+ * \brief Returns true if byte address a is unequal to byte address b
+ */
+bool operator != (const UanAddress &a, const UanAddress &b);
+
+/**
+ * \brief Writes param address to stream os as 8 bit integer
+ */
+std::ostream& operator<< (std::ostream& os, const UanAddress & address);
+
+/**
+ * \brief Inputs param address from stream is as 8 bit integer
+ */
+std::istream& operator>> (std::istream& is, UanAddress & address);
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANADDRESS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-channel.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,221 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "ns3/object.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/mobility-model.h"
+#include "ns3/net-device.h"
+#include "ns3/node.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/log.h"
+
+#include "uan-channel.h"
+#include "uan-phy.h"
+#include "uan-prop-model.h"
+#include "uan-tx-mode.h"
+#include "uan-net-device.h"
+#include "uan-transducer.h"
+#include "uan-noise-model-default.h"
+#include "uan-prop-model-ideal.h"
+
+NS_LOG_COMPONENT_DEFINE ("UanChannel");
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanChannel);
+
+TypeId
+UanChannel::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::UanChannel")
+    .SetParent<Channel> ()
+    .AddConstructor<UanChannel> ()
+    .AddAttribute ("PropagationModel",
+                   "A pointer to the propagation model.",
+                   PointerValue (CreateObject<UanPropModelIdeal> ()),
+                   MakePointerAccessor (&UanChannel::m_prop),
+                   MakePointerChecker<UanPropModel> ())
+    .AddAttribute ("NoiseModel",
+                   "A pointer to the model of the channel ambient noise.",
+                   PointerValue (CreateObject<UanNoiseModelDefault> ()),
+                   MakePointerAccessor (&UanChannel::m_noise),
+                   MakePointerChecker<UanNoiseModel> ())
+  ;
+
+  return tid;
+}
+
+UanChannel::UanChannel ()
+  : Channel (),
+    m_prop (0),
+    m_cleared (false)
+{
+}
+
+UanChannel::~UanChannel ()
+{
+}
+
+void
+UanChannel::Clear ()
+{
+  if (m_cleared)
+    {
+      return;
+    }
+  m_cleared = true;
+  UanDeviceList::iterator it = m_devList.begin ();
+  for (; it != m_devList.end (); it++)
+    {
+      if (it->first)
+        {
+          it->first->Clear ();
+          it->first = 0;
+        }
+      if (it->second)
+        {
+          it->second->Clear ();
+          it->second = 0;
+        }
+    }
+  m_devList.clear ();
+  if (m_prop)
+    {
+      m_prop->Clear ();
+      m_prop = 0;
+    }
+  if (m_noise)
+    {
+      m_noise->Clear ();
+      m_noise = 0;
+    }
+      
+}
+
+void
+UanChannel::DoDispose ()
+{
+  Clear ();
+  Channel::DoDispose ();
+}
+void
+UanChannel::SetPropagationModel (Ptr<UanPropModel> prop)
+{
+  NS_LOG_DEBUG ("Set Prop Model " << this);
+  m_prop = prop;
+}
+
+uint32_t
+UanChannel::GetNDevices () const
+{
+  return m_devList.size ();
+}
+
+Ptr<NetDevice>
+UanChannel::GetDevice (uint32_t i) const
+{
+  return m_devList[i].first;
+}
+
+void
+UanChannel::AddDevice (Ptr<UanNetDevice> dev, Ptr<UanTransducer> trans)
+{
+  NS_LOG_DEBUG ("Adding dev/trans pair number " << m_devList.size ());
+  m_devList.push_back (std::make_pair (dev, trans));
+}
+
+void
+UanChannel::TxPacket (Ptr<UanTransducer> src, Ptr<Packet> packet,
+                      double txPowerDb, UanTxMode txMode)
+{
+  Ptr<MobilityModel> senderMobility = 0;
+
+  NS_LOG_DEBUG ("Channel scheduling");
+  for (UanDeviceList::const_iterator i = m_devList.begin (); i
+       != m_devList.end (); i++)
+    {
+
+      if (src == i->second)
+        {
+          senderMobility = i->first->GetNode ()->GetObject<MobilityModel> ();
+          break;
+        }
+    }
+  NS_ASSERT (senderMobility != 0);
+  uint32_t j = 0;
+  UanDeviceList::const_iterator i = m_devList.begin ();
+  for (; i != m_devList.end (); i++)
+    {
+      if (src != i->second)
+        {
+          NS_LOG_DEBUG ("Scheduling " << i->first->GetMac ()->GetAddress ());
+          Ptr<MobilityModel> rcvrMobility = i->first->GetNode ()->GetObject<MobilityModel> ();
+          Time delay = m_prop->GetDelay (senderMobility, rcvrMobility, txMode);
+          UanPdp pdp = m_prop->GetPdp (senderMobility, rcvrMobility, txMode);
+          double rxPowerDb = txPowerDb + m_prop->GetPathLossDb (senderMobility,
+                                                                rcvrMobility,
+                                                                txMode);
+
+          NS_LOG_DEBUG ("txPowerDb=" << txPowerDb << "dB, rxPowerDb="
+                                     << rxPowerDb << "distance="
+                                     << senderMobility->GetDistanceFrom (rcvrMobility)
+                                     << "m, delay=" << delay);
+
+          uint32_t dstNodeId = i->first->GetNode ()->GetId ();
+          Ptr<Packet> copy = packet->Copy ();
+          Simulator::ScheduleWithContext (dstNodeId, delay,
+                                          &UanChannel::SendUp,
+                                          this,
+                                          j,
+                                          copy,
+                                          rxPowerDb,
+                                          txMode,
+                                          pdp);
+        }
+      j++;
+    }
+}
+
+void
+UanChannel::SetNoiseModel (Ptr<UanNoiseModel> noise)
+{
+  NS_ASSERT (noise);
+  m_noise = noise;
+}
+void
+UanChannel::SendUp (uint32_t i, Ptr<Packet> packet, double rxPowerDb,
+                    UanTxMode txMode, UanPdp pdp)
+{
+  NS_LOG_DEBUG ("Channel:  In sendup");
+  m_devList[i].second->Receive (packet, rxPowerDb, txMode, pdp);
+}
+
+double
+UanChannel::GetNoiseDbHz (double fKhz)
+{
+  NS_ASSERT (m_noise);
+  double noise = m_noise->GetNoiseDbHz (fKhz);
+  return noise;
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-channel.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,117 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANCHANNEL_H
+#define UANCHANNEL_H
+
+#include "ns3/net-device.h"
+#include "ns3/channel.h"
+#include "ns3/packet.h"
+#include "uan-prop-model.h"
+#include "uan-noise-model.h"
+
+#include <list>
+#include <vector>
+
+namespace ns3 {
+namespace uan {
+
+class UanNetDevice;
+class UanPhy;
+class UanTransducer;
+class UanTxMode;
+
+/**
+ * \class UanChannel
+ * \brief Channel class used by UAN devices
+ */
+class UanChannel : public Channel
+{
+public:
+  /**
+   * \brief UanDeviceList is a standard template vector of pairs (UanNetDevice, UanTransducer)
+   */
+  typedef std::vector<std::pair<Ptr<UanNetDevice>, Ptr<UanTransducer> > > UanDeviceList;
+
+
+  UanChannel ();
+  virtual ~UanChannel ();
+
+  static TypeId GetTypeId ();
+
+  // Methods inherrited from base class
+  virtual uint32_t GetNDevices (void) const;
+  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
+
+  /**
+   * \param src Transducer transmitting packet
+   * \param packet Packet to be transmitted
+   * \param txPowerDb Transmission power in dB
+   * \param txmode UanTxMode defining modulation of transmitted packet
+   * Send a packet out on the channel
+   */
+  void TxPacket  (Ptr<UanTransducer> src, Ptr<Packet> packet, double txPowerDb,
+                  UanTxMode txmode);
+
+  /**
+   * \param dev Net Device of node
+   * \param trans Transducer of net device attached to this channel
+   *
+   * Adds device to receiver list for this channel
+   */
+  void AddDevice (Ptr<UanNetDevice> dev, Ptr<UanTransducer> trans);
+
+  /**
+   * \param prop Propagation model this channel will use for path loss/propagation delay
+   */
+  void SetPropagationModel (Ptr<UanPropModel> prop);
+
+  /**
+   * \param noise Noise model this channel will use to determine ambient channel noise.
+   *
+   */
+  void SetNoiseModel  (Ptr<UanNoiseModel> noise);
+
+  /**
+   * \param fKhz Frequency in kHz
+   * \returns Ambient noise in dB/Hz on channel at a frequency
+   */
+  double GetNoiseDbHz (double fKhz);
+
+  /**
+   * Clears all pointer references
+   */
+  void Clear (void);
+
+private:
+  UanDeviceList m_devList;
+  Ptr<UanPropModel> m_prop;
+  Ptr<UanNoiseModel> m_noise;
+  bool m_cleared;
+
+  void SendUp (uint32_t i, Ptr<Packet> packet, double rxPowerDb, UanTxMode txMode, UanPdp pdp);
+protected:
+  virtual void DoDispose ();
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANCHANNEL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-header-common.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,133 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-header-common.h"
+#include "uan-address.h"
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanHeaderCommon);
+
+UanHeaderCommon::UanHeaderCommon ()
+{
+}
+
+UanHeaderCommon::UanHeaderCommon (const UanAddress src, const UanAddress dest, uint8_t type)
+  : Header (),
+    m_dest (dest),
+    m_src (src),
+    m_type (type)
+{
+
+}
+
+TypeId
+UanHeaderCommon::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanHeaderCommon")
+    .SetParent<Header> ()
+    .AddConstructor<UanHeaderCommon> ()
+  ;
+  return tid;
+}
+
+TypeId
+UanHeaderCommon::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+UanHeaderCommon::~UanHeaderCommon ()
+{
+}
+
+
+void
+UanHeaderCommon::SetDest (UanAddress dest)
+{
+  m_dest = dest;
+}
+void
+UanHeaderCommon::SetSrc (UanAddress src)
+{
+  m_src = src;
+}
+
+void
+UanHeaderCommon::SetType (uint8_t type)
+{
+  m_type = type;
+}
+
+UanAddress
+UanHeaderCommon::GetDest (void) const
+{
+  return m_dest;
+}
+UanAddress
+UanHeaderCommon::GetSrc (void) const
+{
+  return m_src;
+}
+uint8_t
+UanHeaderCommon::GetType (void) const
+{
+  return m_type;
+}
+
+// Inherrited methods
+
+uint32_t
+UanHeaderCommon::GetSerializedSize (void) const
+{
+  return 1 + 1 + 1;
+}
+
+void
+UanHeaderCommon::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (m_src.GetAsInt ());
+  start.WriteU8 (m_dest.GetAsInt ());
+  start.WriteU8 (m_type);
+}
+
+uint32_t
+UanHeaderCommon::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator rbuf = start;
+
+  m_src = UanAddress (rbuf.ReadU8 ());
+  m_dest = UanAddress (rbuf.ReadU8 ());
+  m_type = rbuf.ReadU8 ();
+
+  return rbuf.GetDistanceFrom (start);
+}
+
+void
+UanHeaderCommon::Print (std::ostream &os) const
+{
+  os << "UAN src=" << m_src << " dest=" << m_dest << " type=" << (uint32_t) m_type;
+}
+
+
+
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-header-common.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,98 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANHEADERCOMMON_H
+#define UANHEADERCOMMON_H
+
+#include "ns3/header.h"
+#include "ns3/nstime.h"
+#include "ns3/simulator.h"
+#include "uan-address.h"
+
+namespace ns3 {
+namespace uan {
+
+/**
+ * \class UanHeaderCommon
+ *
+ * Header includes 1 byte src address, 1 byte dest address,
+ * and a 1 byte type field.
+ */
+class UanHeaderCommon : public Header
+{
+public:
+  UanHeaderCommon ();
+  /**
+   * \brief Create UanHeaderCommon object with given source and destination address and header type
+   * \param src Source address defined in header
+   * \param dest Destination address defined in header
+   * \param type Header type
+   */
+  UanHeaderCommon (const UanAddress src, const UanAddress dest, uint8_t type);
+  virtual ~UanHeaderCommon ();
+
+  static TypeId GetTypeId (void);
+
+  /**
+   * \param dest Address of destination node
+   */
+  void SetDest (UanAddress dest);
+  /**
+   * \param src Address of packet source node
+   */
+  void SetSrc (UanAddress src);
+  /**
+   * \param type Value to set 1 byte type field to.  Value has protocol specific meaning
+   */
+  void SetType (uint8_t type);
+
+  /**
+   * \returns UanAddress in destination field
+   */
+  UanAddress GetDest (void) const;
+  /**
+   * \returns UanAddress in source field
+   */
+  UanAddress GetSrc (void) const;
+  /**
+   * \returns value of type field
+   */
+  uint8_t GetType (void) const;
+
+
+
+  // Inherrited methods
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+  virtual TypeId GetInstanceTypeId (void) const;
+private:
+  UanAddress m_dest;
+  UanAddress m_src;
+  uint8_t m_type;
+
+
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANHEADERCOMMON_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-header-rc.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,631 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+
+#include "uan-header-rc.h"
+
+#include <set>
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanHeaderRcData);
+NS_OBJECT_ENSURE_REGISTERED (UanHeaderRcRts);
+NS_OBJECT_ENSURE_REGISTERED (UanHeaderRcCtsGlobal);
+NS_OBJECT_ENSURE_REGISTERED (UanHeaderRcCts);
+NS_OBJECT_ENSURE_REGISTERED (UanHeaderRcAck);
+
+UanHeaderRcData::UanHeaderRcData ()
+  : Header (),
+    m_frameNo (0),
+    m_propDelay (Seconds (0))
+{
+}
+
+UanHeaderRcData::UanHeaderRcData (uint8_t frameNo, Time propDelay)
+  : Header (),
+    m_frameNo (frameNo),
+    m_propDelay (propDelay)
+{
+
+}
+
+UanHeaderRcData::~UanHeaderRcData ()
+{
+}
+
+TypeId
+UanHeaderRcData::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::UanHeaderRcData")
+    .SetParent<Header> ()
+    .AddConstructor<UanHeaderRcData> ()
+  ;
+  return tid;
+}
+
+void
+UanHeaderRcData::SetFrameNo (uint8_t no)
+{
+  m_frameNo = no;
+}
+
+void
+UanHeaderRcData::SetPropDelay (Time propDelay)
+{
+  m_propDelay = propDelay;
+}
+
+uint8_t
+UanHeaderRcData::GetFrameNo (void) const
+{
+  return m_frameNo;
+}
+
+Time
+UanHeaderRcData::GetPropDelay (void) const
+{
+  return m_propDelay;
+}
+
+uint32_t
+UanHeaderRcData::GetSerializedSize (void) const
+{
+  return 1 + 2;
+}
+
+void
+UanHeaderRcData::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (m_frameNo);
+  start.WriteU16 ( (uint16_t)(1000.0 * m_propDelay.GetSeconds () + 0.5));
+}
+uint32_t
+UanHeaderRcData::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator rbuf = start;
+
+  m_frameNo = start.ReadU8 ();
+  m_propDelay = Seconds ( ((double) start.ReadU16 ()) / 1000.0 );
+
+  return rbuf.GetDistanceFrom (start);
+}
+
+void
+UanHeaderRcData::Print (std::ostream &os) const
+{
+  os << "Frame No=" << (uint32_t) m_frameNo << " Prop Delay=" << m_propDelay.GetSeconds ();
+}
+
+TypeId
+UanHeaderRcData::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+
+UanHeaderRcRts::UanHeaderRcRts ()
+  : Header (),
+    m_frameNo (0),
+    m_noFrames (0),
+    m_length (0),
+    m_timeStamp (Seconds (0)),
+    m_retryNo (0)
+{
+
+}
+
+UanHeaderRcRts::UanHeaderRcRts (uint8_t frameNo, uint8_t retryNo, uint8_t noFrames, uint16_t length, Time timeStamp)
+  : Header (),
+    m_frameNo (frameNo),
+    m_noFrames (noFrames),
+    m_length (length),
+    m_timeStamp (timeStamp),
+    m_retryNo (retryNo)
+{
+
+}
+
+UanHeaderRcRts::~UanHeaderRcRts ()
+{
+
+}
+
+TypeId
+UanHeaderRcRts::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::UanHeaderRcRts")
+    .SetParent<Header> ()
+    .AddConstructor<UanHeaderRcRts> ()
+  ;
+  return tid;
+
+}
+
+void
+UanHeaderRcRts::SetFrameNo (uint8_t no)
+{
+  m_frameNo = no;
+}
+
+void
+UanHeaderRcRts::SetNoFrames (uint8_t no)
+{
+  m_noFrames = no;
+}
+
+void
+UanHeaderRcRts::SetLength (uint16_t length)
+{
+  m_length = length;
+}
+void
+UanHeaderRcRts::SetTimeStamp (Time timeStamp)
+{
+  m_timeStamp = timeStamp;
+}
+
+void
+UanHeaderRcRts::SetRetryNo (uint8_t no)
+{
+  m_retryNo = no;
+}
+uint8_t
+UanHeaderRcRts::GetNoFrames () const
+{
+  return m_noFrames;
+}
+
+uint16_t
+UanHeaderRcRts::GetLength () const
+{
+  return m_length;
+}
+
+Time
+UanHeaderRcRts::GetTimeStamp (void) const
+{
+  return m_timeStamp;
+}
+
+uint8_t
+UanHeaderRcRts::GetRetryNo (void) const
+{
+  return m_retryNo;
+}
+
+uint8_t
+UanHeaderRcRts::GetFrameNo (void) const
+{
+  return m_frameNo;
+}
+
+uint32_t
+UanHeaderRcRts::GetSerializedSize (void) const
+{
+  return 1 + 1 + 1 + 4 + 2;
+}
+
+void
+UanHeaderRcRts::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (m_frameNo);
+  start.WriteU8 (m_retryNo);
+  start.WriteU8 (m_noFrames);
+  start.WriteU16 (m_length);
+  start.WriteU32 ((uint32_t)(m_timeStamp.GetSeconds () * 1000.0 + 0.5));
+  // start.WriteU16(uint16_t (m_timeStamp.GetSeconds ()*1000));
+}
+
+uint32_t
+UanHeaderRcRts::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator rbuf = start;
+  m_frameNo = rbuf.ReadU8 ();
+  m_retryNo = rbuf.ReadU8 ();
+  m_noFrames = rbuf.ReadU8 ();
+  m_length = rbuf.ReadU16 ();
+  m_timeStamp = Seconds ( ((double) rbuf.ReadU32 ()) / 1000.0 );
+  // m_timeStamp = Seconds ( rbuf.ReadU16 ()/1000 );
+  return rbuf.GetDistanceFrom (start);
+}
+
+void
+UanHeaderRcRts::Print (std::ostream &os) const
+{
+  os << "Frame #=" << (uint32_t) m_frameNo << " Retry #=" << (uint32_t) m_retryNo << " Num Frames=" << (uint32_t) m_noFrames << "Length=" << m_length << " Time Stamp=" << m_timeStamp.GetSeconds ();
+}
+
+TypeId
+UanHeaderRcRts::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+
+
+
+UanHeaderRcCtsGlobal::UanHeaderRcCtsGlobal ()
+  : Header (),
+    m_retryRate (0),
+    m_rateNum (0)
+{
+
+}
+
+UanHeaderRcCtsGlobal::UanHeaderRcCtsGlobal (Time wt, Time ts, uint16_t rate, uint16_t retryRate)
+  : Header (),
+    m_timeStampTx (ts),
+    m_winTime (wt),
+    m_retryRate (retryRate),
+    m_rateNum (rate)
+{
+
+}
+
+UanHeaderRcCtsGlobal::~UanHeaderRcCtsGlobal ()
+{
+
+}
+
+TypeId
+UanHeaderRcCtsGlobal::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::UanHeaderRcCtsGlobal")
+    .SetParent<Header> ()
+    .AddConstructor<UanHeaderRcCtsGlobal> ()
+  ;
+  return tid;
+
+}
+
+
+void
+UanHeaderRcCtsGlobal::SetRateNum (uint16_t rate)
+{
+  m_rateNum = rate;
+}
+
+void
+UanHeaderRcCtsGlobal::SetRetryRate (uint16_t rate)
+{
+  m_retryRate = rate;
+}
+
+void
+UanHeaderRcCtsGlobal::SetWindowTime (Time t)
+{
+  m_winTime = t;
+}
+
+void
+UanHeaderRcCtsGlobal::SetTxTimeStamp (Time t)
+{
+  m_timeStampTx = t;
+}
+
+Time
+UanHeaderRcCtsGlobal::GetWindowTime (void) const
+{
+  return m_winTime;
+}
+
+Time
+UanHeaderRcCtsGlobal::GetTxTimeStamp (void) const
+{
+  return m_timeStampTx;
+}
+
+uint16_t
+UanHeaderRcCtsGlobal::GetRetryRate (void) const
+{
+  return m_retryRate;
+}
+
+uint16_t
+UanHeaderRcCtsGlobal::GetRateNum (void) const
+{
+  return m_rateNum;
+}
+uint32_t
+UanHeaderRcCtsGlobal::GetSerializedSize (void) const
+{
+  return 4 + 4 + 2 + 2;
+}
+
+void
+UanHeaderRcCtsGlobal::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU16 (m_rateNum);
+  start.WriteU16 (m_retryRate);
+  start.WriteU32 ( (uint32_t)(m_timeStampTx.GetSeconds () * 1000.0 + 0.5));
+  start.WriteU32 ( (uint32_t)(m_winTime.GetSeconds () * 1000.0 + 0.5));
+}
+
+uint32_t
+UanHeaderRcCtsGlobal::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator rbuf = start;
+  m_rateNum = rbuf.ReadU16 ();
+  m_retryRate = rbuf.ReadU16 ();
+  m_timeStampTx = Seconds ( ( (double) rbuf.ReadU32 ()) / 1000.0 );
+  m_winTime = Seconds ( ( (double) rbuf.ReadU32 ()) / 1000.0 );
+  return rbuf.GetDistanceFrom (start);
+
+}
+
+void
+UanHeaderRcCtsGlobal::Print (std::ostream &os) const
+{
+  os << "CTS Global (Rate #=" << m_rateNum << ", Retry Rate=" << m_retryRate << ", TX Time=" << m_timeStampTx.GetSeconds () << ", Win Time=" << m_winTime.GetSeconds () << ")";
+}
+
+TypeId
+UanHeaderRcCtsGlobal::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+UanHeaderRcCts::UanHeaderRcCts ()
+  : Header (),
+    m_frameNo (0),
+    m_timeStampRts (Seconds (0)),
+    m_retryNo (0),
+    m_delay (Seconds (0)),
+    m_address (UanAddress::GetBroadcast ())
+{
+
+}
+
+UanHeaderRcCts::UanHeaderRcCts (uint8_t frameNo, uint8_t retryNo, Time ts, Time delay, UanAddress addr)
+  : Header (),
+    m_frameNo (frameNo),
+    m_timeStampRts (ts),
+    m_retryNo (retryNo),
+    m_delay (delay),
+    m_address (addr)
+{
+
+}
+
+UanHeaderRcCts::~UanHeaderRcCts ()
+{
+
+}
+
+TypeId
+UanHeaderRcCts::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::UanHeaderRcCts")
+    .SetParent<Header> ()
+    .AddConstructor<UanHeaderRcCts> ()
+  ;
+  return tid;
+
+}
+
+void
+UanHeaderRcCts::SetFrameNo (uint8_t frameNo)
+{
+  m_frameNo = frameNo;
+}
+
+void
+UanHeaderRcCts::SetRtsTimeStamp (Time timeStamp)
+{
+  m_timeStampRts = timeStamp;
+}
+
+
+void
+UanHeaderRcCts::SetDelayToTx (Time delay)
+{
+  m_delay = delay;
+}
+
+void
+UanHeaderRcCts::SetRetryNo (uint8_t no)
+{
+  m_retryNo = no;
+}
+
+void
+UanHeaderRcCts::SetAddress (UanAddress addr)
+{
+  m_address = addr;
+}
+uint8_t
+UanHeaderRcCts::GetFrameNo () const
+{
+  return m_frameNo;
+}
+
+Time
+UanHeaderRcCts::GetRtsTimeStamp (void) const
+{
+  return m_timeStampRts;
+}
+
+Time
+UanHeaderRcCts::GetDelayToTx (void) const
+{
+  return m_delay;
+}
+
+uint8_t
+UanHeaderRcCts::GetRetryNo () const
+{
+  return m_retryNo;
+}
+
+UanAddress
+UanHeaderRcCts::GetAddress () const
+{
+  return m_address;
+}
+
+uint32_t
+UanHeaderRcCts::GetSerializedSize (void) const
+{
+  return 1 + 1 + 1 + 4 + 4;
+}
+
+
+void
+UanHeaderRcCts::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (m_address.GetAsInt ());
+  start.WriteU8 (m_frameNo);
+  start.WriteU8 (m_retryNo);
+  start.WriteU32 ((uint32_t)(m_timeStampRts.GetSeconds () * 1000.0 + 0.5));
+  start.WriteU32 ((uint32_t)(m_delay.GetSeconds () * 1000.0 + 0.5));
+}
+
+uint32_t
+UanHeaderRcCts::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator rbuf = start;
+  m_address = UanAddress (rbuf.ReadU8 ());
+  m_frameNo = rbuf.ReadU8 ();
+  m_retryNo = rbuf.ReadU8 ();
+  m_timeStampRts = Seconds ( ( (double) rbuf.ReadU32 ()) / 1000.0 );
+  m_delay = Seconds ( ( (double) rbuf.ReadU32 ()) / 1000.0 );
+
+  return rbuf.GetDistanceFrom (start);
+}
+
+void
+UanHeaderRcCts::Print (std::ostream &os) const
+{
+  os << "CTS (Addr=" << m_address << " Frame #=" << (uint32_t) m_frameNo << " Retry #=" << (uint32_t) m_retryNo << " RTS Rx Timestamp=" << m_timeStampRts.GetSeconds () << " Delay until TX=" << m_delay.GetSeconds () << ")";
+}
+
+TypeId
+UanHeaderRcCts::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+UanHeaderRcAck::UanHeaderRcAck ()
+  : m_frameNo (0)
+{
+}
+
+UanHeaderRcAck::~UanHeaderRcAck ()
+{
+  m_nackedFrames.clear ();
+}
+
+TypeId
+UanHeaderRcAck::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::UanHeaderRcAck")
+    .SetParent<Header> ()
+    .AddConstructor<UanHeaderRcAck> ()
+  ;
+  return tid;
+}
+
+void
+UanHeaderRcAck::SetFrameNo (uint8_t noFrames)
+{
+  m_frameNo = noFrames;
+}
+
+void
+UanHeaderRcAck::AddNackedFrame (uint8_t frame)
+{
+  m_nackedFrames.insert (frame);
+}
+
+const std::set<uint8_t> &
+UanHeaderRcAck::GetNackedFrames (void) const
+{
+  return m_nackedFrames;
+}
+
+uint8_t
+UanHeaderRcAck::GetFrameNo (void) const
+{
+  return m_frameNo;
+}
+
+uint8_t
+UanHeaderRcAck::GetNoNacks (void) const
+{
+  return m_nackedFrames.size ();
+}
+
+uint32_t
+UanHeaderRcAck::GetSerializedSize (void) const
+{
+  return 1 + 1 + GetNoNacks ();
+}
+
+void
+UanHeaderRcAck::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (m_frameNo);
+  start.WriteU8 (GetNoNacks ());
+  std::set<uint8_t>::iterator it = m_nackedFrames.begin ();
+  for (; it != m_nackedFrames.end (); it++)
+    {
+      start.WriteU8 (*it);
+    }
+}
+
+uint32_t
+UanHeaderRcAck::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator rbuf = start;
+  m_frameNo = rbuf.ReadU8 ();
+  uint8_t noAcks = rbuf.ReadU8 ();
+  m_nackedFrames.clear ();
+  for (uint32_t i = 0; i < noAcks; i++)
+    {
+      m_nackedFrames.insert (rbuf.ReadU8 ());
+    }
+  return rbuf.GetDistanceFrom (start);
+}
+
+void
+UanHeaderRcAck::Print (std::ostream &os) const
+{
+  os << "# Frames=" << (uint32_t) m_frameNo << " # nacked=" << (uint32_t) GetNoNacks () << " Nacked: ";
+  if (GetNoNacks () > 0)
+    {
+      std::set<uint8_t>::iterator it = m_nackedFrames.begin ();
+      os << (uint32_t) *it;
+      it++;
+      for (; it != m_nackedFrames.end (); it++)
+        {
+          os << ", " << (uint32_t) *it;
+        }
+    }
+}
+
+TypeId
+UanHeaderRcAck::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-header-rc.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,377 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+
+#ifndef UANHEADERRC_H
+#define UANHEADERRC_H
+
+#include "ns3/header.h"
+#include "ns3/nstime.h"
+#include "uan-address.h"
+
+#include <set>
+
+namespace ns3 {
+namespace uan {
+
+/**
+ * \class UanHeaderRcData
+ *
+ * \brief Extra data header information
+ *
+ * Adds prop. delay measure, and frame number info to
+ * transmitted data packet
+ */
+class UanHeaderRcData : public Header
+{
+public:
+  UanHeaderRcData ();
+  /**
+   * \param frameNum Data frame # of reservation being transmitted
+   * \param propDelay  Measured propagation delay found in handshaking
+   * \note Prop. delay is transmitted with 16 bits and ms accuracy
+   */
+  UanHeaderRcData (uint8_t frameNum, Time propDelay);
+  virtual ~UanHeaderRcData ();
+
+  static TypeId GetTypeId (void);
+
+  /**
+   * \param frameNum Data frame # of reservation being transmitted
+   */
+  void SetFrameNo (uint8_t frameNum);
+  /**
+   * \param propDelay Measured propagation delay found in handshaking
+   * \note Prop. delay is transmitted with 16 bits and ms accuracy
+   */
+  void SetPropDelay (Time propDelay);
+  /**
+   * \returns Data frame # of reservation being transmitted
+   */
+  uint8_t GetFrameNo (void) const;
+  /**
+   * \returns Measured propagation delay found in handshaking
+   * \note Prop. delay is transmitted with 16 bits and ms accuracy
+   */
+  Time GetPropDelay (void) const;
+
+  // Inherrited methods
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+  virtual TypeId GetInstanceTypeId (void) const;
+
+private:
+  uint8_t m_frameNo;
+  Time m_propDelay;
+};
+
+/**
+ * \class UanHeaderRcRts
+ *
+ * \brief RTS header
+ *
+ * Contains frame #, retry #, # frames, length, and timestamp
+ */
+class UanHeaderRcRts : public Header
+{
+public:
+  UanHeaderRcRts ();
+  /**
+   * \param frameNo Reservation frame #
+   * \param retryNo Retry # of RTS packet
+   * \param noFrames # of data frames in reservation
+   * \param length # of bytes (including headers) in data
+   * \param ts RTS TX timestamp
+   * \note Timestamp is serialized into 32 bits with ms accuracy
+   */
+  UanHeaderRcRts (uint8_t frameNo, uint8_t retryNo, uint8_t noFrames, uint16_t length, Time ts);
+  virtual ~UanHeaderRcRts ();
+
+  static TypeId GetTypeId (void);
+
+  /**
+   * \param fno TX frame #
+   */
+  void SetFrameNo (uint8_t fno);
+  /**
+   * \param no Number of data frames included in this reservation request
+   */
+  void SetNoFrames (uint8_t no);
+  /**
+   * \param timeStamp RTS transmission time
+   */
+  void SetTimeStamp (Time timeStamp);
+  /**
+   * \param length Total number of data bytes in reservation (including headers)
+   * \note Timestamp is serialized with 32 bits in ms precision
+   */
+  void SetLength (uint16_t length);
+  /**
+   * \param no Retry number of this RTS (Used to match timestamp to correctly received RTS)
+   */
+  void SetRetryNo (uint8_t no);
+
+  /**
+   * \returns Frame #
+   */
+  uint8_t GetFrameNo (void) const;
+  /**
+   * \returns # of data frames in reservation
+   */
+  uint8_t GetNoFrames (void) const;
+  /**
+   * \returns TX time of the RTS packet
+   * \note Timestamp is serialized with 32 bits in ms precision
+   */
+  Time GetTimeStamp (void) const;
+  /**
+   * \returns Total # of bytes in data packets for reservation (including headers)
+   */
+  uint16_t GetLength (void) const;
+  /**
+   * \returns Retry number of this RTS packet
+   */
+  uint8_t GetRetryNo (void) const;
+
+  // Inherrited methods
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+  virtual TypeId GetInstanceTypeId (void) const;
+
+private:
+  uint8_t m_frameNo;
+  uint8_t m_noFrames;
+  uint16_t m_length;
+  Time m_timeStamp;
+  uint8_t m_retryNo;
+};
+
+/**
+ * \class UanHeaderRcCtsGlobal
+ *
+ * \brief Cycle broadcast information for
+ */
+
+
+class UanHeaderRcCtsGlobal : public Header
+{
+public:
+  /**
+   * \brief Create UanHeaderRcCtsGlobal with fields zeroed out
+   */
+  UanHeaderRcCtsGlobal ();
+  /**
+   * \brief Create object with given window time, time stamp, rate, and retry rate.
+   * \param wt Window time
+   * \param ts Timestamp
+   * \param rate Rate number
+   * \param retryRate  Retry rate value
+   */
+  UanHeaderRcCtsGlobal (Time wt, Time ts, uint16_t rate, uint16_t retryRate);
+  ~UanHeaderRcCtsGlobal ();
+
+  static TypeId GetTypeId (void);
+
+  /**
+   * \param rate Rate number corresponding to data rate of current cycle
+   */
+  void SetRateNum (uint16_t rate);
+  /**
+   * \param rate Retry rate number for current cycle
+   */
+  void SetRetryRate (uint16_t rate);
+  /**
+   * \param t Time duration following blocking time to allow RTS transmissions
+   */
+  void SetWindowTime (Time t);
+
+  /**
+   * \param timeStamp Time of CTS transmission
+   */
+  void SetTxTimeStamp (Time timeStamp);
+
+  /**
+   * \returns Rate # corresponding to data rate of current cycle
+   */
+  uint16_t GetRateNum (void) const;
+  /**
+   * \returns retry rate # of retry rate for current cycle
+   */
+  uint16_t GetRetryRate (void) const;
+  /**
+   * \returns Time duration after blocking time allowed for RTS transmissions
+   */
+  Time GetWindowTime (void) const;
+  /**
+   * \returns Timestamp of CTS transmission
+   */
+  Time GetTxTimeStamp (void) const;
+
+  // Inherrited methods
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+  virtual TypeId GetInstanceTypeId (void) const;
+
+private:
+  Time m_timeStampTx;
+  Time m_winTime;
+  uint16_t m_retryRate;
+  uint16_t m_rateNum;
+};
+/**
+ * \class UanHeaderRcCts
+ *
+ * \brief CTS header
+ *
+ * Includes RTS RX time, CTS TX time, delay until TX, RTS blocking period,
+ * RTS tx period, rate #, and retry rate #
+ */
+
+class UanHeaderRcCts : public Header
+{
+public:
+  UanHeaderRcCts ();
+  /**
+   * \param frameNo Resrvation frame # being cleared
+   * \param retryNo Retry # of received RTS packet
+   * \param rtsTs RX time of RTS packet at gateway
+   * \param delay Delay until transmission
+   * \param addr Destination of CTS packet
+   * \note Times are serialized, with ms precission, into 32 bit fields.
+   */
+  UanHeaderRcCts (uint8_t frameNo, uint8_t retryNo, Time rtsTs, Time delay, UanAddress addr);
+  virtual ~UanHeaderRcCts ();
+
+  static TypeId GetTypeId (void);
+
+  /**
+   * \param frameNo Frame # of RTS being cleared
+   */
+  void SetFrameNo (uint8_t frameNo);
+  /**
+   * \param timeStamp Time of RTS reception
+   */
+  void SetRtsTimeStamp (Time timeStamp);
+  /**
+   * \param delay Time duration, from CTS TX, before first data frame arrival
+   */
+  void SetDelayToTx (Time delay);
+  /**
+   * \param no Retry number of RTS frame being cleared
+   */
+  void SetRetryNo (uint8_t no);
+  /**
+   * \param addr Destination for scheduling info
+   */
+  void SetAddress (UanAddress addr);
+
+  /**
+   * \returns Frame # of RTS being cleared
+   */
+  uint8_t GetFrameNo (void) const;
+  /**
+   * \returns RX time of RTS being cleared
+   */
+  Time GetRtsTimeStamp (void) const;
+  /**
+   * \returns Delay from TX time of CTS packet until arrival of first data frame
+   */
+  Time GetDelayToTx (void) const;
+  /**
+   * \returns Retry # of RTS packet being cleared
+   */
+  uint8_t GetRetryNo (void) const;
+  /**
+   * \returns Destination for scheduling info
+   */
+  UanAddress GetAddress (void) const;
+
+  // Inherrited methods
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+  virtual TypeId GetInstanceTypeId (void) const;
+
+private:
+  uint8_t m_frameNo;
+  Time m_timeStampRts;
+  uint8_t m_retryNo;
+  Time m_delay;
+  UanAddress m_address;
+};
+
+/**
+ * \class UanHeaderRcAck
+ * \brief Header used for ACK packets by protocol ns3::UanMacRc
+ */
+class UanHeaderRcAck : public Header
+{
+public:
+  UanHeaderRcAck ();
+  virtual ~UanHeaderRcAck ();
+
+  static TypeId GetTypeId (void);
+
+  /**
+   * \param frameNo Frame # of reservation being acknowledged
+   */
+  void SetFrameNo (uint8_t frameNo);
+  /**
+   * \param frame Data frame # being nacked
+   */
+  void AddNackedFrame (uint8_t frame);
+
+  /**
+   * \returns Set of nacked frames
+   */
+  const std::set<uint8_t> &GetNackedFrames (void) const;
+  /**
+   * \returns Reservation frame # being acknowledged.
+   */
+  uint8_t GetFrameNo (void) const;
+  /**
+   * \returns Number of data frames being NACKED
+   */
+  uint8_t GetNoNacks (void) const;
+
+  // Inherrited methods
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual void Print (std::ostream &os) const;
+  virtual TypeId GetInstanceTypeId (void) const;
+
+private:
+  uint8_t m_frameNo;
+  std::set<uint8_t> m_nackedFrames;
+
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANHEADERRC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac-aloha.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,155 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-mac-aloha.h"
+#include "uan-tx-mode.h"
+#include "uan-address.h"
+#include "ns3/log.h"
+#include "uan-phy.h"
+#include "uan-header-common.h"
+
+#include <iostream>
+NS_LOG_COMPONENT_DEFINE ("UanMacAloha");
+
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanMacAloha);
+
+UanMacAloha::UanMacAloha ()
+  : UanMac (),
+    m_cleared (false)
+{
+}
+
+UanMacAloha::~UanMacAloha ()
+{
+}
+
+void
+UanMacAloha::Clear ()
+{
+  if (m_cleared)
+    {
+      return;
+    }
+  m_cleared = true;
+  if (m_phy)
+    {
+      m_phy->Clear ();
+      m_phy = 0;
+    }
+}
+
+void
+UanMacAloha::DoDispose ()
+{
+  Clear ();
+  UanMac::DoDispose ();
+}
+
+TypeId
+UanMacAloha::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanMacAloha")
+    .SetParent<Object> ()
+    .AddConstructor<UanMacAloha> ()
+  ;
+  return tid;
+}
+
+Address
+UanMacAloha::GetAddress (void)
+{
+  return m_address;
+}
+
+void
+UanMacAloha::SetAddress (UanAddress addr)
+{
+  m_address=addr;
+}
+bool
+UanMacAloha::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
+{
+  NS_LOG_DEBUG ("" << Simulator::Now ().GetSeconds () << " MAC " << UanAddress::ConvertFrom (GetAddress ()) << " Queueing packet for " << UanAddress::ConvertFrom (dest));
+
+  if (!m_phy->IsStateTx ())
+    {
+      UanAddress src = UanAddress::ConvertFrom (GetAddress ());
+      UanAddress udest = UanAddress::ConvertFrom (dest);
+
+      UanHeaderCommon header;
+      header.SetSrc (src);
+      header.SetDest (udest);
+      header.SetType (0);
+
+      packet->AddHeader (header);
+      m_phy->SendPacket (packet, protocolNumber);
+      return true;
+    }
+  else
+    return false;
+}
+
+void
+UanMacAloha::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress& > cb)
+{
+  m_forUpCb = cb;
+}
+void
+UanMacAloha::AttachPhy (Ptr<UanPhy> phy)
+{
+  m_phy = phy;
+  m_phy->SetReceiveOkCallback (MakeCallback (&UanMacAloha::RxPacketGood, this));
+  m_phy->SetReceiveErrorCallback (MakeCallback (&UanMacAloha::RxPacketError, this));
+
+}
+void
+UanMacAloha::RxPacketGood (Ptr<Packet> pkt, double sinr, UanTxMode txMode)
+{
+  UanHeaderCommon header;
+  pkt->RemoveHeader (header);
+  NS_LOG_DEBUG ("Receiving packet from " << header.GetSrc () << " For " << header.GetDest ());
+
+  if (header.GetDest () == GetAddress () || header.GetDest () == UanAddress::GetBroadcast ())
+    {
+      m_forUpCb (pkt, header.GetSrc ());
+    }
+
+}
+
+void
+UanMacAloha::RxPacketError (Ptr<Packet> pkt, double sinr)
+{
+  NS_LOG_DEBUG ("" << Simulator::Now () << " MAC " << UanAddress::ConvertFrom (GetAddress ()) << " Received packet in error with sinr " << sinr);
+}
+
+Address
+UanMacAloha::GetBroadcast (void) const
+{
+  UanAddress broadcast (255);
+  return broadcast;
+}
+
+} // namespace uan
+} // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac-aloha.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,87 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANMACALOHA_H
+#define UANMACALOHA_H
+
+#include "uan-mac.h"
+#include "uan-address.h"
+
+namespace ns3 {
+namespace uan {
+
+
+class UanPhy;
+class UanTxMode;
+
+/**
+ * \class UanMacAloha
+ * \brief ALOHA MAC Protocol
+ *
+ * The simplest MAC protocol for wireless networks.  Packets enqueued
+ * are immediately transmitted.  This MAC attaches a UanHeaderCommon
+ * to outgoing packets for address information.  (The type field is not used)
+ */
+class UanMacAloha : public UanMac
+{
+public:
+  UanMacAloha ();
+  virtual ~UanMacAloha ();
+  static TypeId GetTypeId (void);
+
+
+  //Inheritted functions
+  Address GetAddress (void);
+  virtual void SetAddress (UanAddress addr);
+  virtual bool Enqueue (Ptr<Packet> pkt, const Address &dest, uint16_t protocolNumber);
+  virtual void SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress& > cb);
+  virtual void AttachPhy (Ptr<UanPhy> phy);
+  virtual Address GetBroadcast (void) const;
+  virtual void Clear (void);
+
+private:
+  UanAddress m_address;
+  Ptr<UanPhy> m_phy;
+  Callback<void, Ptr<Packet>, const UanAddress& > m_forUpCb;
+  bool m_cleared;
+
+  /**
+   * \brief Receive packet from lower layer (passed to PHY as callback)
+   * \param pkt Packet being received
+   * \param sinr SINR of received packet
+   * \param txMode Mode of received packet
+   */
+  void RxPacketGood (Ptr<Packet> pkt, double sinr, UanTxMode txMode);
+
+  /**
+   * \brief Packet received at lower layer in error
+   * \param pkt Packet received in error
+   * \param sinr SINR of received packet
+   */
+  void RxPacketError (Ptr<Packet> pkt, double sinr);
+protected:
+  virtual void DoDispose ();
+};
+
+} // namespace uan
+} // namespace ns3
+
+
+#endif // UANMACALOHA_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac-cw.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,389 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-mac-cw.h"
+#include "ns3/attribute.h"
+#include "ns3/uinteger.h"
+#include "ns3/double.h"
+#include "ns3/nstime.h"
+#include "ns3/random-variable.h"
+#include "uan-header-common.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("UanMacCw");
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanMacCw);
+
+UanMacCw::UanMacCw ()
+  : UanMac (),
+    m_phy (0),
+    m_pktTx (0),
+    m_state (IDLE),
+    m_cleared (false)
+
+{
+}
+
+UanMacCw::~UanMacCw ()
+{
+}
+
+void
+UanMacCw::Clear ()
+{
+  if (m_cleared)
+    {
+      return;
+    }
+  m_cleared = true;
+  m_pktTx = 0;
+  if (m_phy)
+    {
+      m_phy->Clear ();
+      m_phy = 0;
+    }
+  m_sendEvent.Cancel ();
+  m_txEndEvent.Cancel ();
+}  
+
+void
+UanMacCw::DoDispose ()
+{
+  Clear ();
+  UanMac::DoDispose ();
+}
+
+TypeId
+UanMacCw::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanMacCw")
+    .SetParent<Object> ()
+    .AddConstructor<UanMacCw> ()
+    .AddAttribute ("CW",
+                   "The MAC parameter CW",
+                   UintegerValue (10),
+                   MakeUintegerAccessor (&UanMacCw::m_cw),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("SlotTime",
+                   "Time slot duration for MAC backoff",
+                   TimeValue (MilliSeconds (20)),
+                   MakeTimeAccessor (&UanMacCw::m_slotTime),
+                   MakeTimeChecker ())
+    .AddTraceSource ("Enqueue",
+                     "A packet arrived at the MAC for transmission",
+                     MakeTraceSourceAccessor (&UanMacCw::m_enqueueLogger))
+    .AddTraceSource ("Dequeue",
+                     "A was passed down to the PHY from the MAC",
+                     MakeTraceSourceAccessor (&UanMacCw::m_dequeueLogger))
+    .AddTraceSource ("RX",
+                     "A packet was destined for this MAC and was received",
+                     MakeTraceSourceAccessor (&UanMacCw::m_rxLogger))
+
+  ;
+  return tid;
+}
+
+Address
+UanMacCw::GetAddress ()
+{
+  return this->m_address;
+}
+
+void
+UanMacCw::SetAddress (UanAddress addr)
+{
+  m_address = addr;
+}
+
+bool
+UanMacCw::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
+{
+
+  switch (m_state)
+    {
+    case CCABUSY:
+      NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " MAC " << GetAddress () << " Starting enqueue CCABUSY");
+      if (m_txEndEvent.IsRunning () == TX)
+        {
+          NS_LOG_DEBUG ("State is TX");
+        }
+      else
+        {
+          NS_LOG_DEBUG ("State is not TX");
+        }
+
+      NS_ASSERT (m_phy->GetTransducer ()->GetArrivalList ().size () >= 1 || m_phy->IsStateTx ());
+      return false;
+    case RUNNING:
+      NS_LOG_DEBUG ("MAC " << GetAddress () << " Starting enqueue RUNNING");
+      NS_ASSERT (m_phy->GetTransducer ()->GetArrivalList ().size () == 0 && !m_phy->IsStateTx ());
+      return false;
+    case TX:
+    case IDLE:
+      {
+        NS_ASSERT (!m_pktTx);
+
+        UanHeaderCommon header;
+        header.SetDest (UanAddress::ConvertFrom (dest));
+        header.SetSrc (m_address);
+        header.SetType (0);
+        packet->AddHeader (header);
+
+        m_enqueueLogger (packet, protocolNumber);
+
+        if (m_phy->IsStateBusy ())
+          {
+            m_pktTx = packet;
+            m_pktTxProt = protocolNumber;
+            m_state = CCABUSY;
+            UniformVariable rv (0,m_cw);
+            uint32_t cw = (uint32_t) rv.GetValue ();
+            m_savedDelayS = Seconds ((double)(cw) * m_slotTime.GetSeconds ());
+            m_sendTime = Simulator::Now () + m_savedDelayS;
+            NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << ": Addr " << GetAddress () << ": Enqueuing new packet while busy:  (Chose CW " << cw << ", Sending at " << m_sendTime.GetSeconds () << " Packet size: " << packet->GetSize ());
+            NS_ASSERT (m_phy->GetTransducer ()->GetArrivalList ().size () >= 1 || m_phy->IsStateTx ());
+          }
+        else
+          {
+            NS_ASSERT (m_state != TX);
+            NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << ": Addr " << GetAddress () << ": Enqueuing new packet while idle (sending)");
+            NS_ASSERT (m_phy->GetTransducer ()->GetArrivalList ().size () == 0 && !m_phy->IsStateTx ());
+            m_state = TX;
+            m_phy->SendPacket (packet,protocolNumber);
+
+          }
+        break;
+      }
+    default:
+      NS_LOG_DEBUG ("MAC " << GetAddress () << " Starting enqueue SOMETHING ELSE");
+      return false;
+    }
+
+  return true;
+
+
+}
+
+void
+UanMacCw::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb)
+{
+  m_forwardUpCb = cb;
+}
+
+void
+UanMacCw::AttachPhy (Ptr<UanPhy> phy)
+{
+  m_phy = phy;
+  m_phy->SetReceiveOkCallback (MakeCallback (&UanMacCw::PhyRxPacketGood, this));
+  m_phy->SetReceiveErrorCallback (MakeCallback (&UanMacCw::PhyRxPacketError, this));
+  m_phy->RegisterListener (this);
+}
+
+Address
+UanMacCw::GetBroadcast (void) const
+{
+  return UanAddress::GetBroadcast ();
+}
+
+
+void
+UanMacCw::NotifyRxStart (void)
+{
+  if (m_state == RUNNING)
+    {
+
+      NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel busy");
+      SaveTimer ();
+      m_state = CCABUSY;
+    }
+
+}
+void
+UanMacCw::NotifyRxEndOk (void)
+{
+  if (m_state == CCABUSY && !m_phy->IsStateCcaBusy ())
+    {
+      NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel idle");
+      m_state = RUNNING;
+      StartTimer ();
+
+    }
+
+}
+void
+UanMacCw::NotifyRxEndError (void)
+{
+  if (m_state == CCABUSY && !m_phy->IsStateCcaBusy ())
+    {
+      NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel idle");
+      m_state = RUNNING;
+      StartTimer ();
+
+    }
+
+}
+void
+UanMacCw::NotifyCcaStart (void)
+{
+  if (m_state == RUNNING)
+    {
+      NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel busy");
+      m_state = CCABUSY;
+      SaveTimer ();
+
+    }
+
+}
+void
+UanMacCw::NotifyCcaEnd (void)
+{
+  if (m_state == CCABUSY)
+    {
+      NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel idle");
+      m_state = RUNNING;
+      StartTimer ();
+
+    }
+
+}
+void
+UanMacCw::NotifyTxStart (Time duration)
+{
+
+  if (m_txEndEvent.IsRunning ())
+    {
+      Simulator::Cancel (m_txEndEvent);
+    }
+
+  m_txEndEvent = Simulator::Schedule (duration, &UanMacCw::EndTx, this);
+  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " scheduling TxEndEvent with delay " << duration.GetSeconds ());
+  if (m_state == RUNNING)
+    {
+      NS_ASSERT (0);
+      m_state = CCABUSY;
+      SaveTimer ();
+
+    }
+
+}
+
+void
+UanMacCw::EndTx (void)
+{
+  NS_ASSERT (m_state == TX || m_state == CCABUSY);
+  if (m_state == TX)
+    {
+      m_state = IDLE;
+    }
+  else if (m_state == CCABUSY)
+    {
+      if (m_phy->IsStateIdle ())
+        {
+          NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel idle (After TX!)");
+          m_state = RUNNING;
+          StartTimer ();
+        }
+    }
+  else
+    {
+      NS_FATAL_ERROR ("In strange state at UanMacCw EndTx");
+    }
+}
+void
+UanMacCw::SetCw (uint32_t cw)
+{
+  m_cw = cw;
+}
+void
+UanMacCw::SetSlotTime (Time duration)
+{
+  m_slotTime = duration;
+}
+uint32_t
+UanMacCw::GetCw (void)
+{
+  return m_cw;
+}
+Time
+UanMacCw::GetSlotTime (void)
+{
+  return m_slotTime;
+}
+void
+UanMacCw::PhyRxPacketGood (Ptr<Packet> packet, double sinr, UanTxMode mode)
+{
+  UanHeaderCommon header;
+  packet->RemoveHeader (header);
+
+  if (header.GetDest () == m_address)
+    {
+      m_forwardUpCb (packet, header.GetSrc ());
+    }
+}
+void
+UanMacCw::PhyRxPacketError (Ptr<Packet> packet, double sinr)
+{
+
+}
+void
+UanMacCw::SaveTimer (void)
+{
+  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << " Saving timer (Delay = " << (m_savedDelayS = m_sendTime - Simulator::Now ()).GetSeconds () << ")");
+  NS_ASSERT (m_pktTx);
+  NS_ASSERT (m_sendTime >= Simulator::Now ());
+  m_savedDelayS = m_sendTime - Simulator::Now ();
+  Simulator::Cancel (m_sendEvent);
+
+
+}
+void
+UanMacCw::StartTimer (void)
+{
+
+  m_sendTime = Simulator::Now () + m_savedDelayS;
+  if (m_sendTime == Simulator::Now ())
+    {
+      SendPacket ();
+    }
+  else
+    {
+      m_sendEvent = Simulator::Schedule (m_savedDelayS, &UanMacCw::SendPacket, this);
+      NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << " Starting timer (New send time = " << this->m_sendTime.GetSeconds () << ")");
+    }
+}
+
+void
+UanMacCw::SendPacket (void)
+{
+  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << " Transmitting ");
+  NS_ASSERT (m_state == RUNNING);
+  m_state = TX;
+  m_phy->SendPacket (m_pktTx,m_pktTxProt);
+  m_pktTx = 0;
+  m_sendTime = Seconds (0);
+  m_savedDelayS = Seconds (0);
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac-cw.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,131 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANMACCW_H
+#define UANMACCW_H
+
+#include "uan-mac.h"
+#include "ns3/nstime.h"
+#include "ns3/simulator.h"
+#include "uan-phy.h"
+#include "uan-tx-mode.h"
+#include "uan-address.h"
+
+
+namespace ns3 {
+namespace uan {
+
+/**
+ * \class UanMacCw
+ * \brief CW-MAC A MAC protocol similar in idea to the 802.11 DCF with constant backoff window
+ *
+ * For more information on this MAC protocol, see:
+ * Parrish, N.; Tracy, L.; Roy, S.; Arabshahi, P.; Fox, W.,
+ * "System Design Considerations for Undersea Networks: Link and Multiple Access Protocols,"
+ * Selected Areas in Communications, IEEE Journal on , vol.26, no.9, pp.1720-1730, December 2008
+ */
+class UanMacCw : public UanMac,
+                 public UanPhyListener
+{
+public:
+  UanMacCw ();
+  virtual ~UanMacCw ();
+  static TypeId GetTypeId (void);
+
+  /**
+   * \param cw Contention window size
+   */
+  virtual void SetCw (uint32_t cw);
+  /**
+   * \param duration Slot time duration
+   */
+  virtual void SetSlotTime (Time duration);
+  /**
+   * \returns Contention window size
+   */
+  virtual uint32_t GetCw (void);
+  /**
+   * \returns slot time duration
+   */
+  virtual Time GetSlotTime (void);
+
+  // Inherited methods
+  virtual Address GetAddress ();
+  virtual void SetAddress (UanAddress addr);
+  virtual bool Enqueue (Ptr<Packet> pkt, const Address &dest, uint16_t protocolNumber);
+  virtual void SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb);
+  virtual void AttachPhy (Ptr<UanPhy> phy);
+  virtual Address GetBroadcast (void) const;
+  virtual void Clear (void);
+
+  // PHY listeners
+  /// Function called by UanPhy object to notify of packet reception
+  virtual void NotifyRxStart (void);
+  /// Function called by UanPhy object to notify of packet received successfully
+  virtual void NotifyRxEndOk (void);
+  /// Function called by UanPhy object to notify of packet received in error
+  virtual void NotifyRxEndError (void);
+  /// Function called by UanPhy object to notify of channel sensed busy
+  virtual void NotifyCcaStart (void);
+  /// Function called by UanPhy object to notify of channel no longer sensed busy
+  virtual void NotifyCcaEnd (void);
+  /// Function called by UanPhy object to notify of outgoing transmission start
+  virtual void NotifyTxStart (Time duration);
+private:
+  typedef enum {
+    IDLE, CCABUSY, RUNNING, TX
+  } State;
+
+  Callback <void, Ptr<Packet>, const UanAddress& > m_forwardUpCb;
+  UanAddress m_address;
+  Ptr<UanPhy> m_phy;
+  TracedCallback<Ptr<const Packet>, UanTxMode > m_rxLogger;
+  TracedCallback<Ptr<const Packet>, uint16_t  > m_enqueueLogger;
+  TracedCallback<Ptr<const Packet>, uint16_t  > m_dequeueLogger;
+
+  // Mac parameters
+  uint32_t m_cw;
+  Time m_slotTime;
+
+  // State variables
+  Time m_sendTime;
+  Time m_savedDelayS;
+  Ptr<Packet> m_pktTx;
+  uint16_t m_pktTxProt;
+  EventId m_sendEvent;
+  EventId m_txEndEvent;
+  State m_state;
+
+  bool m_cleared;
+
+  void PhyRxPacketGood (Ptr<Packet> packet, double sinr, UanTxMode mode);
+  void PhyRxPacketError (Ptr<Packet> packet, double sinr);
+  void SaveTimer (void);
+  void StartTimer (void);
+  void SendPacket (void);
+  void EndTx (void);
+protected:
+  virtual void DoDispose ();
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANMACCW_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac-rc-gw.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,737 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-mac-rc-gw.h"
+#include "uan-mac-rc.h"
+#include "uan-header-common.h"
+#include "uan-header-rc.h"
+#include "uan-phy.h"
+#include "uan-tx-mode.h"
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/nstime.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+
+#include <utility>
+#include <set>
+#include <map>
+#include <vector>
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("UanMacRcGw");
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanMacRcGw);
+
+bool
+operator < (const UanAddress &a, const UanAddress &b)
+{
+  return a.GetAsInt () < b.GetAsInt ();
+}
+
+
+UanMacRcGw::UanMacRcGw ()
+  : UanMac (),
+    m_state (IDLE),
+    m_currentRateNum (0),
+    m_cleared (false)
+{
+  UanHeaderCommon ch;
+  UanHeaderRcRts rts;
+  UanHeaderRcCts cts;
+  UanHeaderRcAck ack;
+  UanHeaderRcCtsGlobal ctsg;
+
+  m_rtsSize = ch.GetSerializedSize () + rts.GetSerializedSize ();
+  m_ctsSizeN = cts.GetSerializedSize ();
+  m_ctsSizeG = ch.GetSerializedSize () + ctsg.GetSerializedSize ();
+  m_ackSize = ch.GetSerializedSize () + ack.GetSerializedSize ();
+
+  NS_LOG_DEBUG ("Gateway initialized");
+}
+
+UanMacRcGw::~UanMacRcGw ()
+{
+}
+
+void
+UanMacRcGw::Clear ()
+{
+  if (m_cleared)
+    {
+      return;
+    }
+  m_cleared = true;
+  if (m_phy)
+    {
+      m_phy->Clear ();
+      m_phy = 0;
+    }
+  m_propDelay.clear ();
+  std::map<UanAddress, AckData>::iterator it = m_ackData.begin ();
+  for (; it != m_ackData.end (); it++)
+    {
+      it->second.rxFrames.clear ();
+    }
+  m_ackData.clear ();
+  m_requests.clear ();
+  m_sortedRes.clear ();
+}
+
+void
+UanMacRcGw::DoDispose ()
+{
+  Clear ();
+  UanMac::DoDispose ();
+}
+TypeId
+UanMacRcGw::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanMacRcGw")
+    .SetParent<UanMac> ()
+    .AddConstructor<UanMacRcGw> ()
+    .AddAttribute ("MaxReservations",
+                   "Maximum number of reservations to accept per cycle",
+                   UintegerValue (10),
+                   MakeUintegerAccessor (&UanMacRcGw::m_maxRes),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("NumberOfRates",
+                   "Number of rates per Phy layer",
+                   UintegerValue (1023),
+                   MakeUintegerAccessor (&UanMacRcGw::m_numRates),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RetryRate",
+                   "Number of retry rates per second at non-gateway nodes",
+                   DoubleValue (1 / 10.0),
+                   MakeDoubleAccessor (&UanMacRcGw::m_retryRate),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxPropDelay",
+                   "Maximum propagation delay between gateway and non-gateway nodes",
+                   TimeValue (Seconds (2)),
+                   MakeTimeAccessor (&UanMacRcGw::m_maxDelta),
+                   MakeTimeChecker ())
+    .AddAttribute ("SIFS",
+                   "Spacing between frames to account for timing error and processing delay",
+                   TimeValue (Seconds (0.2)),
+                   MakeTimeAccessor (&UanMacRcGw::m_sifs),
+                   MakeTimeChecker ())
+    .AddAttribute ("NumberOfNodes",
+                   "Number of non-gateway nodes in this gateway's neighborhood",
+                   UintegerValue (10),
+                   MakeUintegerAccessor (&UanMacRcGw::m_numNodes),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinRetryRate",
+                   "Smallest allowed RTS retry rate",
+                   DoubleValue (0.01),
+                   MakeDoubleAccessor (&UanMacRcGw::m_minRetryRate),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RetryStep",
+                   "Retry rate increment",
+                   DoubleValue (0.01),
+                   MakeDoubleAccessor (&UanMacRcGw::m_retryStep),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("NumberOfRetryRates",
+                   "Number of retry rates",
+                   UintegerValue (100),
+                   MakeUintegerAccessor (&UanMacRcGw::m_numRetryRates),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("TotalRate",
+                   "Total available channel rate in bps (for a single channel, without splitting reservation channel)",
+                   UintegerValue (4096),
+                   MakeUintegerAccessor (&UanMacRcGw::m_totalRate),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RateStep",
+                   "Increments available for rate assignment in bps",
+                   UintegerValue (4),
+                   MakeUintegerAccessor (&UanMacRcGw::m_rateStep),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("FrameSize",
+                   "Size of data frames in bytes",
+                   UintegerValue (1000),
+                   MakeUintegerAccessor (&UanMacRcGw::m_frameSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddTraceSource ("RX",
+                     "A packet was destined for and received at this MAC layer",
+                     MakeTraceSourceAccessor (&UanMacRcGw::m_rxLogger))
+    .AddTraceSource ("Cycle",
+                     "Trace cycle statistics",
+                     MakeTraceSourceAccessor (&UanMacRcGw::m_cycleLogger))
+
+  ;
+
+  return tid;
+}
+
+Address
+UanMacRcGw::GetAddress (void)
+{
+  return m_address;
+}
+
+void
+UanMacRcGw::SetAddress (UanAddress addr)
+{
+  m_address = addr;
+}
+
+bool
+UanMacRcGw::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
+{
+  NS_LOG_WARN ("RCMAC Gateway transmission to acoustic nodes is not yet implemented");
+  return false;
+}
+
+void
+UanMacRcGw::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb)
+{
+  m_forwardUpCb = cb;
+}
+
+void
+UanMacRcGw::AttachPhy (Ptr<UanPhy> phy)
+{
+  m_phy = phy;
+  phy->SetReceiveOkCallback (MakeCallback (&UanMacRcGw::ReceivePacket, this));
+  phy->SetReceiveErrorCallback (MakeCallback (&UanMacRcGw::ReceiveError, this));
+}
+
+void
+UanMacRcGw::ReceiveError (Ptr<Packet> pkt, double sinr)
+{
+}
+
+Address
+UanMacRcGw::GetBroadcast (void) const
+{
+  return UanAddress::GetBroadcast ();
+}
+
+void
+UanMacRcGw::ReceivePacket (Ptr<Packet> pkt, double sinr, UanTxMode mode)
+{
+  UanHeaderCommon ch;
+  pkt->PeekHeader (ch);
+
+  if (ch.GetDest () == m_address || ch.GetDest () == UanAddress::GetBroadcast ())
+    {
+      m_rxLogger (pkt, mode);
+    }
+  else
+    {
+      return;
+    }
+
+  pkt->RemoveHeader (ch);
+
+  switch (ch.GetType ())
+    {
+    case UanMacRc::TYPE_DATA:
+      {
+        UanHeaderRcData dh;
+        pkt->RemoveHeader (dh);
+        m_propDelay[ch.GetSrc ()] = dh.GetPropDelay ();
+        if (m_ackData.find (ch.GetSrc ()) == m_ackData.end ())
+          {
+            NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GATEWAY Received unexpected data packet");
+          }
+        else
+          {
+            NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW Received data packet from " << ch.GetSrc () << " length = " << pkt->GetSize ());
+            m_ackData[ch.GetSrc ()].rxFrames.insert (dh.GetFrameNo ());
+          }
+        m_forwardUpCb (pkt, ch.GetSrc ());
+      }
+      break;
+    case UanMacRc::TYPE_GWPING:
+    case UanMacRc::TYPE_RTS:
+      if (m_state == CTSING)
+        {
+          return;
+        }
+
+      {
+        UanHeaderRcRts rh;
+        pkt->RemoveHeader (rh);
+
+        if (m_requests.find (ch.GetSrc ()) == m_requests.end ())
+          {
+            Request req;
+            req.numFrames = rh.GetNoFrames ();
+            req.rxTime = Simulator::Now ();
+            req.frameNo = rh.GetFrameNo ();
+            req.retryNo = rh.GetRetryNo ();
+            req.length = rh.GetLength ();
+            NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW storing reservation from " << ch.GetSrc () << " with length " << req.length);
+            m_requests.insert (std::make_pair (ch.GetSrc (), req));
+            std::map<UanAddress, Time>::iterator it = m_propDelay.find (ch.GetSrc ());
+            if (it == m_propDelay.end ())
+              {
+                m_sortedRes.insert (std::make_pair (m_maxDelta, ch.GetSrc ()));
+              }
+            else
+              {
+                m_sortedRes.insert (std::make_pair ( (*it).second, ch.GetSrc ()));
+              }
+          }
+      }
+      if (m_state == IDLE)
+        {
+          StartCycle ();
+        }
+      break;
+    case UanMacRc::TYPE_CTS:
+      NS_FATAL_ERROR ("Received CTS at GW.  Currently only support single GW network!");
+      break;
+    case UanMacRc::TYPE_ACK:
+      NS_FATAL_ERROR ("Received ACK at GW.  Currently only support single GW network!");
+      break;
+    default:
+      NS_FATAL_ERROR ("Received unknown packet at GW!");
+    }
+}
+
+void
+UanMacRcGw::StartCycle (void)
+{
+  uint32_t numRts = m_sortedRes.size ();
+
+  if (numRts)
+    {
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Simulator starting non-empty cycle");
+    }
+  else
+    {
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Simulator starting EMPTY cycle");
+    }
+
+  // Calculate dataRate
+  uint32_t totalBytes = 0;
+  uint32_t totalFrames = 0;
+  double pDelay = 0;
+  if (numRts > 0)
+    {
+      std::map<UanAddress, Request>::iterator rit = m_requests.begin ();
+      for (; rit != m_requests.end (); rit++)
+        {
+          totalBytes += (*rit).second.length;
+          totalFrames += (*rit).second.numFrames;
+        }
+      pDelay = 2 * m_sortedRes.begin ()->first.GetSeconds ();
+    }
+
+
+  double minRate = m_phy->GetMode (m_numRates).GetDataRateBps ();
+
+  uint32_t optA = m_maxRes;
+  if (m_maxRes == 0)
+    {
+      optA = FindOptA ();
+    }
+  double thAlpha = ComputeAlpha (totalFrames, totalBytes, m_numNodes, optA, pDelay / 2.0);
+
+  double thCtlRate = m_totalRate * thAlpha;
+
+  double temprate = (thCtlRate - minRate) / ((double) m_rateStep) + 0.5;
+  m_currentRateNum =  (uint32_t) temprate;
+  if (m_currentRateNum >= m_numRates)
+    {
+      m_currentRateNum = m_numRates - 1;
+    }
+
+  NS_LOG_DEBUG ("Found theoretical alpha: " << thAlpha << " Found associated rate = " << thCtlRate << " Giving rate number: " << temprate);
+  double thX = thAlpha * m_totalRate / (2.0 * m_numNodes * m_rtsSize * 8.0);
+
+  double dataRate = m_phy->GetMode (m_currentRateNum).GetDataRateBps ();
+
+
+  if (thX < m_minRetryRate)
+    {
+      NS_LOG_WARN ("Gateway found optimum RTS retry rate is below minimum");
+      m_currentRetryRate = 0;
+    }
+  else
+    {
+      m_currentRetryRate = (uint16_t)((thX - m_minRetryRate) / m_retryStep + 0.5) ;
+    }
+
+  double actualX = m_currentRetryRate * m_retryStep + m_minRetryRate;
+
+  uint32_t ctlRate =  m_phy->GetMode (m_currentRateNum + m_numRates).GetDataRateBps ();
+
+
+  double winSize = (double)(totalBytes) * 8.0 / dataRate + m_sifs.GetSeconds () * totalFrames + pDelay;
+  if (numRts == 0)
+    {
+      winSize = (optA * exp (1.0) + 0.5) * 2.0 * 8.0 * m_rtsSize / (thAlpha * m_totalRate) + 2 * m_maxDelta.GetSeconds ();
+    }
+  double effWinSize = winSize - m_rtsSize * 8 / ctlRate  - 2 * m_maxDelta.GetSeconds ();
+
+
+  // Before fast CTS/ACK(below)
+  double cycleSeconds = winSize + (totalFrames + 1.0) * m_sifs.GetSeconds () + m_ctsSizeG * 8.0 / dataRate + (m_ctsSizeN + m_ackSize) * 8.0 * numRts / dataRate;
+
+  Time ctsTxTimeG = Seconds (m_ctsSizeG * 8.0 / dataRate);
+  Time ctsTxTimeTotal = Seconds (m_ctsSizeN * 8.0 * numRts / dataRate) + ctsTxTimeG;
+  if (numRts == 0)
+    {
+      UanHeaderRcCtsGlobal ctsg;
+      ctsg.SetWindowTime (Seconds (effWinSize));
+      ctsg.SetRateNum (m_currentRateNum);
+      ctsg.SetRetryRate (m_currentRetryRate);
+      ctsg.SetTxTimeStamp (Simulator::Now ());
+
+      UanHeaderCommon ch (m_address, UanAddress::GetBroadcast (), UanMacRc::TYPE_CTS);
+      Ptr<Packet> p = Create<Packet> ();
+      p->AddHeader (ctsg);
+      p->AddHeader (ch);
+      SendPacket (p, m_currentRateNum);
+
+
+      Simulator::Schedule (Seconds (cycleSeconds), &UanMacRcGw::StartCycle, this);
+      m_state = INCYCLE;
+      m_cycleLogger (Simulator::Now (), Seconds (0), numRts, totalBytes, effWinSize, ctlRate, actualX);
+      return;
+    }
+
+  Time nextEarliest = ctsTxTimeTotal + m_sifs;
+
+  m_state = CTSING;
+  Simulator::Schedule (nextEarliest, &UanMacRcGw::CycleStarted, this);
+
+  std::set<std::pair<Time, UanAddress> >::iterator it = m_sortedRes.begin ();
+  Time minPdelay = (*it).first;
+  Ptr<Packet> cts = Create<Packet> ();
+
+  for (; it != m_sortedRes.end (); it++)
+    {
+      Request req = m_requests[(*it).second];
+      Time pdelay = (*it).first;
+
+      AckData newData;
+      newData.expFrames = req.numFrames;
+      newData.frameNo = req.frameNo;
+      UanAddress dest = (*it).second;
+      m_ackData.insert (std::make_pair (dest, newData));
+
+      Time earliestArr = ctsTxTimeTotal + pdelay + pdelay + m_sifs;
+      Time arrivalTime = std::max (earliestArr, nextEarliest);
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW: Scheduling request for prop. delay " << pdelay.GetSeconds () << " for " << (*it).second << " Earliest possible arrival=" << earliestArr.GetSeconds () << "  Next arrival time=" << nextEarliest.GetSeconds ());
+      nextEarliest = arrivalTime + Seconds (req.length * 8.0 / dataRate) + Seconds (m_sifs.GetSeconds () * req.numFrames);
+
+      UanHeaderRcCts ctsh;
+      ctsh.SetAddress (dest);
+      ctsh.SetRtsTimeStamp (req.rxTime);
+      ctsh.SetFrameNo (req.frameNo);
+      ctsh.SetRetryNo (req.retryNo);
+      ctsh.SetDelayToTx (arrivalTime);
+      cts->AddHeader (ctsh);
+
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW Scheduling reception for " << (uint32_t) req.numFrames << " frames at " << (Simulator::Now () + arrivalTime).GetSeconds () << "  (delaytiltx of " << arrivalTime.GetSeconds () << ")  Total length is " << req.length << " with txtime " << req.length * 8 / dataRate << " seconds");
+    }
+
+  UanHeaderRcCtsGlobal ctsg;
+  ctsg.SetRateNum (m_currentRateNum);
+  ctsg.SetRetryRate (m_currentRetryRate);
+  ctsg.SetWindowTime (Seconds (effWinSize));
+  ctsg.SetTxTimeStamp (Simulator::Now ());
+  UanHeaderCommon ch;
+  ch.SetDest (UanAddress::GetBroadcast ());
+  ch.SetSrc (m_address);
+  ch.SetType (UanMacRc::TYPE_CTS);
+  cts->AddHeader (ctsg);
+  cts->AddHeader (ch);
+  SendPacket (cts, m_currentRateNum);
+
+  m_requests.clear ();
+  m_sortedRes.clear ();
+  Simulator::Schedule (nextEarliest, &UanMacRcGw::EndCycle, this);
+
+
+  m_cycleLogger (Simulator::Now (), minPdelay, numRts, totalBytes, cycleSeconds, ctlRate, actualX);
+}
+
+void
+UanMacRcGw::CycleStarted ()
+{
+  m_state = INCYCLE;
+}
+void
+UanMacRcGw::EndCycle ()
+{
+
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW Ending cycle");
+
+  Time nextAck = Seconds (0);
+
+  Time ackTime = Seconds (m_ackSize * 8.0 / m_phy->GetMode (m_currentRateNum).GetDataRateBps ());
+
+  std::map<UanAddress, AckData>::iterator it = m_ackData.begin ();
+  for (; it != m_ackData.end (); it++)
+    {
+      UanAddress dest = (*it).first;
+      AckData &data = (*it).second;
+
+      std::list<uint32_t> toNack;
+      for (uint32_t i = 0; i < data.expFrames; i++)
+        {
+          if (data.rxFrames.find (i) == data.rxFrames.end ())
+            {
+              toNack.push_back (i);
+            }
+        }
+      UanHeaderCommon ch;
+      ch.SetDest (dest);
+      ch.SetSrc (m_address);
+      ch.SetType (UanMacRc::TYPE_ACK);
+      UanHeaderRcAck ah;
+      ah.SetFrameNo (data.frameNo);
+      std::list<uint32_t>::iterator nit = toNack.begin ();
+      for (; nit != toNack.end (); nit++)
+        {
+          ah.AddNackedFrame (*nit);
+        }
+
+      Ptr<Packet> ack = Create<Packet> ();
+      ack->AddHeader (ah);
+      ack->AddHeader (ch);
+      Simulator::Schedule (nextAck, &UanMacRcGw::SendPacket, this, ack, m_currentRateNum);
+      nextAck = nextAck + ackTime + m_sifs;
+    }
+  m_ackData.clear ();
+  Simulator::Schedule (nextAck, &UanMacRcGw::StartCycle, this);
+
+}
+void
+UanMacRcGw::SendPacket (Ptr<Packet> pkt, uint32_t rate)
+{
+  UanHeaderCommon ch;
+  pkt->PeekHeader (ch);
+  std::string type;
+  switch (ch.GetType ())
+    {
+    case UanMacRc::TYPE_DATA:
+      type = "DATA";
+      break;
+    case UanMacRc::TYPE_RTS:
+      type = "RTS";
+      break;
+    case UanMacRc::TYPE_CTS:
+      type = "CTS";
+      break;
+    case UanMacRc::TYPE_ACK:
+      type = "ACK";
+      break;
+    case UanMacRc::TYPE_GWPING:
+      type = "GWPING";
+      break;
+    default:
+      type = "UNKNOWN";
+      break;
+    }
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW sending " << type << " packet with size " << pkt->GetSize () << " to " << ch.GetDest () << " at rate " << rate);
+  m_phy->SendPacket (pkt, rate);
+}
+
+
+double
+UanMacRcGw::ComputeAlpha (uint32_t totalFrames, uint32_t totalBytes, uint32_t n, uint32_t a, double deltaK)
+{
+
+  double alpha;
+  double lrae = m_rtsSize * 8.0*a*std::exp (1.0);
+  if (totalFrames == 0)
+    {
+
+      alpha =  (2.0 * lrae + 8.0 * m_rtsSize - std::sqrt (m_ctsSizeG * 8.0 * 8.0 * m_rtsSize + 2 * 8.0 * m_ctsSizeG * 8.0 * m_rtsSize * a * std::exp (1.0)) ) /
+        (2 * lrae + 8.0 * m_rtsSize - 8.0 * m_ctsSizeG);
+    }
+  else
+    {
+      double w = totalBytes * 8.0 + totalFrames*m_sifs.GetSeconds () * m_totalRate;
+      double v = m_rtsSize * 8.0 + 2 * lrae;
+      double u = (2 * m_maxDelta.GetSeconds () - 2 * deltaK) * m_totalRate;
+
+      double gamma = (w - u + v) / (2 * (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
+
+      alpha = -gamma + sqrt (gamma * gamma + v / (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
+
+      if (alpha < 0 || alpha > 1)
+        {
+          alpha = -gamma - sqrt (gamma * gamma + v / (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
+        }
+    }
+  NS_ASSERT_MSG (alpha > 0 && alpha < 1, "Error computing alpha.  Alpha out of valid range!");
+  return alpha;
+}
+
+std::vector<double>
+UanMacRcGw::GetExpPdk (void)
+{
+  uint32_t n = m_numNodes;
+  std::vector<double> pds;
+  std::map<UanAddress, Time>::iterator pdit = m_propDelay.begin ();
+
+  for (; pdit != m_propDelay.end (); pdit++)
+    {
+      pds.push_back (pdit->second.GetSeconds ());
+    }
+  while (pds.size () < m_numNodes)
+    {
+      pds.push_back (m_maxDelta.GetSeconds ());
+    }
+
+  std::sort (pds.begin (), pds.end ());
+  // Find expected min. prop. delay for k nodes
+  std::vector<double> exppdk;
+  exppdk.push_back (m_maxDelta.GetSeconds ());
+  for (uint32_t k = 1; k <= n; k++)
+    {
+      uint32_t ind = CompExpMinIndex (n,k) - 1;
+      exppdk.push_back (pds[ind]);
+    }
+  return exppdk;
+}
+
+double
+UanMacRcGw::ComputeExpS (uint32_t a, uint32_t ld, std::vector<double> exppdk)
+{
+  UanHeaderCommon ch;
+  uint32_t lh = ch.GetSerializedSize ();
+
+  uint32_t n = m_numNodes;
+  double expk = n * (1 - std::exp (-((double) a) / (double) n));
+  NS_LOG_DEBUG ("expk = " << expk);
+
+  // Compute expected data per cycle
+  double expdata = 8 * ld * expk;
+
+  // Compute expected time per cycle
+  double alpha0 = ComputeAlpha (0,0,n,a,exppdk[0]);
+  double c0 = 8.0 * m_ctsSizeG / ( m_totalRate * (1 - alpha0)) + 2 * m_maxDelta.GetSeconds () + (a * std::exp (1.0) + 0.5) * 2 * m_rtsSize * 8.0 / (alpha0 * m_totalRate);
+  double exptime = ComputePiK (a,n,0) * c0;
+  double expp = 0;
+  for (uint32_t i = 1; i <= n; i++)
+    {
+      expp += ComputePiK (a,n,i) * exppdk[i - 1];
+    }
+
+  exptime += ComputeExpBOverA (n,a,ld + lh,exppdk) + expk * 2 * m_sifs.GetSeconds () + m_sifs.GetSeconds () + 2 * expp;
+  double s = (1.0 / m_totalRate) * expdata / exptime;
+
+  return s;
+}
+
+double
+UanMacRcGw::ComputeExpS (uint32_t a, uint32_t ld)
+{
+  return ComputeExpS (a, ld, GetExpPdk ());
+}
+
+uint32_t
+UanMacRcGw::CompExpMinIndex (uint32_t n, uint32_t k)
+{
+  double sum = 0;
+  for (uint32_t i = 1; i <= n - k + 1; i++)
+    {
+      double p = (double) NchooseK (n - i, k - 1) / NchooseK (n, k);
+      sum += p * i;
+    }
+  return (uint32_t)(sum + 0.5);
+}
+
+double
+UanMacRcGw::ComputePiK (uint32_t a, uint32_t n, uint32_t k)
+{
+  double nck = (double) NchooseK (n, k);
+  return nck * std::pow ( (std::exp ( (double) a / (double) n) - 1.0), (double) k) * std::exp (-( (double) a));
+}
+
+double
+UanMacRcGw::ComputeExpBOverA (uint32_t n, uint32_t a, uint32_t ldlh, std::vector<double> deltaK)
+{
+
+  double sum = 0;
+  uint32_t lt = 8 * (m_ctsSizeN + ldlh + m_ackSize);
+  for (uint32_t k = 1; k <= n; k++)
+    {
+      double num = 8.0 * m_ctsSizeG + k * lt;
+      double denom = (1.0 - ComputeAlpha (k, k * ldlh, n, a, deltaK[k])) * m_totalRate;
+      double pik = ComputePiK (a, n, k);
+      double term = pik * num / denom;
+
+      sum += term;
+    }
+
+  return sum;
+}
+
+uint64_t
+UanMacRcGw::NchooseK (uint32_t n, uint32_t k)
+{
+  if (k > n)
+    {
+      return 0;
+    }
+
+  if (k > n / 2)
+    {
+      k = n - k;
+    }
+
+  double accum = 1;
+  for (uint32_t i = 1; i <= k; i++)
+    {
+      accum = accum * (n - k + i) / i;
+    }
+
+  return (uint64_t)(accum + 0.5);
+
+}
+
+uint32_t
+UanMacRcGw::FindOptA (void)
+{
+  double tput = 0;
+  uint32_t a = 1;
+  while (1)
+    {
+
+      double newtput = ComputeExpS (a, m_frameSize);
+      if (newtput < tput)
+        {
+          a--;
+          break;
+        }
+      else
+        {
+          tput = newtput;
+          a++;
+        }
+    }
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW: Found optimum a = " << a);
+  return a;
+}
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac-rc-gw.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,169 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANMACRCGW_H
+#define UANMACRCGW_H
+
+#include "uan-mac.h"
+#include "uan-address.h"
+
+#include "ns3/nstime.h"
+#include "ns3/traced-callback.h"
+
+
+
+
+#include <set>
+#include <map>
+
+namespace ns3 {
+namespace uan {
+
+class UanTxMode;
+
+/**
+ * \class UanMacRcGw
+ *
+ * \brief Gateway side of RC-MAC
+ *
+ *
+ *
+ * This MAC protocol assumes a network topology where all traffic
+ * is destined for a set of GW nodes which are connected via
+ * some out of band (RF?) means.  UanMacRcGw is the protocol
+ * which runs on the gateway nodes.
+ *
+ * This particular implementation
+ * assumes that there is only a single gateway.
+ *
+ * For more information on class operation email
+ * lentracy@u.washington.edu
+ * (This work is, as of yet, unpublished)
+ */
+
+class UanMacRcGw : public UanMac
+{
+public:
+  UanMacRcGw ();
+  virtual ~UanMacRcGw ();
+
+  static TypeId GetTypeId (void);
+
+  // Inherited virtual functions
+  virtual Address GetAddress (void);
+  virtual void SetAddress (UanAddress addr);
+  virtual bool Enqueue (Ptr<Packet> pkt, const Address &dest, uint16_t protocolNumber);
+  virtual void SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb);
+  virtual void AttachPhy (Ptr<UanPhy> phy);
+  virtual Address GetBroadcast (void) const;
+  virtual void Clear (void);
+
+private:
+  enum State {
+    IDLE, INCYCLE, CTSING
+  };
+  State m_state;
+
+  struct Request
+  {
+    uint8_t numFrames;
+    uint8_t frameNo;
+    uint8_t retryNo;
+    uint16_t length;
+    Time rxTime;
+  };
+
+  struct AckData
+  {
+    uint8_t frameNo;
+    std::set<uint8_t> rxFrames;
+    uint8_t expFrames;
+  };
+  Callback<void, Ptr<Packet>, const UanAddress& > m_forwardUpCb;
+  Ptr<UanPhy> m_phy;
+  UanAddress m_address;
+  Time m_maxDelta;
+  Time m_sifs;
+  uint32_t m_maxRes;
+  uint32_t m_numRates;
+  uint32_t m_rtsSize;
+  uint32_t m_ctsSizeN;
+  uint32_t m_ctsSizeG;
+  uint32_t m_ackSize;
+  double m_retryRate;
+  uint16_t m_currentRetryRate;
+  uint32_t m_currentRateNum;
+  uint32_t m_numNodes;
+  uint32_t m_totalRate;
+  uint32_t m_rateStep;
+  uint32_t m_frameSize;
+
+  uint16_t m_numRetryRates;
+  double m_minRetryRate;
+  double m_retryStep;
+
+  std::map<UanAddress, Time> m_propDelay;
+
+  std::map<UanAddress, AckData> m_ackData;
+
+
+  std::map<UanAddress, Request> m_requests;
+  std::set<std::pair<Time, UanAddress> > m_sortedRes;
+
+  bool m_cleared;
+
+  TracedCallback<Ptr<const Packet>, UanTxMode > m_rxLogger;
+
+  // Start time, min p-delay, reservations, frames, bytes, window size, ctl rate, retry rate
+  TracedCallback<Time, Time, uint32_t, uint32_t, double, uint32_t, double> m_cycleLogger;
+
+  void ReceivePacket (Ptr<Packet> pkt, double sinr, UanTxMode mode);
+  void StartCycle (void);
+  void EndCycle (void);
+  void SendPacket (Ptr<Packet> pkt, uint32_t rate);
+  void CycleStarted (void);
+  void ReceiveError (Ptr<Packet> pkt, double sinr);
+
+  // Stuff for computing exp throughput
+  double ComputeAlpha (uint32_t totalFrames, uint32_t totalBytes, uint32_t n, uint32_t a, double deltaK);
+  std::vector<double>  GetExpPdk (void);
+  double ComputeExpS (uint32_t a, uint32_t ld, std::vector<double> exppdk);
+  double ComputeExpS (uint32_t a, uint32_t ld);
+  uint32_t CompExpMinIndex (uint32_t n, uint32_t k);
+  double ComputePiK (uint32_t a, uint32_t n, uint32_t k);
+  double ComputeExpBOverA (uint32_t n, uint32_t a, uint32_t ldlh, std::vector<double> deltaK);
+  uint64_t NchooseK (uint32_t n, uint32_t k);
+  uint32_t FindOptA (void);
+protected:
+  virtual void DoDispose ();
+
+};
+
+/**
+ * \brief Defined for use in UanMacRcGw
+ * \param a Address to compare
+ * \param b Address to compare
+ */
+bool operator < (const UanAddress &a, const UanAddress &b);
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANMACRCGW_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac-rc.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,774 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-mac-rc.h"
+#include "uan-header-rc.h"
+#include "uan-tx-mode.h"
+#include "uan-phy.h"
+#include "uan-header-common.h"
+#include "uan-phy-dual.h"
+
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+#include "ns3/simulator.h"
+#include "ns3/random-variable.h"
+#include "ns3/assert.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+
+#include <list>
+#include <utility>
+
+
+
+NS_LOG_COMPONENT_DEFINE ("UanMacRc");
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanMacRc);
+
+Reservation::Reservation ()
+  : m_length (0),
+    m_frameNo (0),
+    m_retryNo (0),
+    m_transmitted (false)
+{
+
+}
+
+Reservation::Reservation (std::list<std::pair <Ptr<Packet>, UanAddress > > &list, uint8_t frameNo, uint32_t maxPkts)
+  : m_frameNo (frameNo),
+    m_retryNo (0),
+    m_transmitted (false)
+{
+  uint32_t numPkts = (maxPkts) ? maxPkts : list.size ();
+  uint32_t length = 0;
+  UanHeaderRcData dh;
+  UanHeaderCommon ch;
+
+  for (uint32_t i = 0; i < numPkts; i++)
+    {
+      length += list.front ().first->GetSize () +
+        ch.GetSerializedSize () +
+        dh.GetSerializedSize ();
+      m_pktList.push_back (list.front ());
+      list.pop_front ();
+    }
+  m_length = length;
+}
+
+Reservation::~Reservation ()
+{
+  std::list<std::pair <Ptr<Packet>, UanAddress > >::iterator it;
+  for (it = m_pktList.begin (); it != m_pktList.end (); it++)
+    {
+      it->first = Ptr<Packet> ((Packet *) 0);
+    }
+  m_pktList.clear ();
+  m_timestamp.clear ();
+}
+uint32_t
+Reservation::GetNoFrames () const
+{
+  return m_pktList.size ();
+}
+
+uint32_t
+Reservation::GetLength () const
+{
+  return m_length;
+}
+
+const std::list<std::pair <Ptr<Packet>, UanAddress > > &
+Reservation::GetPktList (void) const
+{
+  return m_pktList;
+}
+
+uint8_t
+Reservation::GetFrameNo () const
+{
+  return m_frameNo;
+}
+
+uint8_t
+Reservation::GetRetryNo () const
+{
+  return m_retryNo;
+}
+
+Time
+Reservation::GetTimestamp (uint8_t n) const
+{
+  return m_timestamp[n];
+}
+
+bool
+Reservation::IsTransmitted () const
+{
+  return m_transmitted;
+}
+
+void
+Reservation::SetFrameNo (uint8_t fn)
+{
+  m_frameNo = fn;
+}
+
+void
+Reservation::AddTimestamp (Time t)
+{
+  m_timestamp.push_back (t);
+}
+
+void
+Reservation::IncrementRetry ()
+{
+  m_retryNo++;
+}
+
+void
+Reservation::SetTransmitted (bool t)
+{
+  m_transmitted = true;
+}
+
+uint32_t UanMacRc::m_cntrlSends = 0;
+
+UanMacRc::UanMacRc ()
+  : UanMac (),
+    m_state (UNASSOCIATED),
+    m_rtsBlocked (false),
+    m_currentRate (10),
+    m_frameNo (0),
+    m_cleared (false)
+{
+  UanHeaderCommon ch;
+  UanHeaderRcCts ctsh;
+  UanHeaderRcCtsGlobal ctsg;
+
+  m_ctsSizeN = ctsh.GetSerializedSize ();
+  m_ctsSizeG = ch.GetSerializedSize () + ctsg.GetSerializedSize ();
+}
+
+UanMacRc::~UanMacRc ()
+{
+}
+
+void
+UanMacRc::Clear ()
+{
+  if (m_cleared)
+    {
+      return;
+    }
+  m_cleared = true;
+  if (m_phy)
+    {
+      m_phy->Clear ();
+      m_phy = 0;
+    }
+  std::list<std::pair <Ptr<Packet>, UanAddress > >::iterator it;
+  for (it = m_pktQueue.begin (); it != m_pktQueue.end (); it++)
+    {
+      it->first = 0;
+    }
+  m_pktQueue.clear ();
+  m_resList.clear ();
+  m_startAgain.Cancel ();
+  m_rtsEvent.Cancel ();
+}
+
+void
+UanMacRc::DoDispose ()
+{
+  Clear ();
+  UanMac::DoDispose ();
+}
+
+TypeId
+UanMacRc::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanMacRc")
+    .SetParent<UanMac> ()
+    .AddConstructor<UanMacRc> ()
+    .AddAttribute ("RetryRate",
+                   "Number of retry attempts per second (of RTS/GWPING)",
+                   DoubleValue (1 / 5.0),
+                   MakeDoubleAccessor (&UanMacRc::m_retryRate),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxFrames",
+                   "Maximum number of frames to include in a single RTS",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&UanMacRc::m_maxFrames),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("QueueLimit",
+                   "Maximum packets to queue at MAC",
+                   UintegerValue (10),
+                   MakeUintegerAccessor (&UanMacRc::m_queueLimit),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("SIFS",
+                   "Spacing to give between frames (this should match gateway)",
+                   TimeValue (Seconds (0.2)),
+                   MakeTimeAccessor (&UanMacRc::m_sifs),
+                   MakeTimeChecker ())
+    .AddAttribute ("NumberOfRates",
+                   "Number of rate divisions supported by each PHY",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&UanMacRc::m_numRates),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinRetryRate",
+                   "Smallest allowed RTS retry rate",
+                   DoubleValue (0.01),
+                   MakeDoubleAccessor (&UanMacRc::m_minRetryRate),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RetryStep",
+                   "Retry rate increment",
+                   DoubleValue (0.01),
+                   MakeDoubleAccessor (&UanMacRc::m_retryStep),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("NumberOfRetryRates",
+                   "Number of retry rates",
+                   UintegerValue (100),
+                   MakeUintegerAccessor (&UanMacRc::m_numRetryRates),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("MaxPropDelay",
+                   "Maximum possible propagation delay to gateway",
+                   TimeValue (Seconds (2)),
+                   MakeTimeAccessor (&UanMacRc::m_learnedProp),
+                   MakeTimeChecker ())
+    .AddTraceSource ("Enqueue",
+                     "A  (data) packet arrived at MAC for transmission",
+                     MakeTraceSourceAccessor (&UanMacRc::m_enqueueLogger))
+    .AddTraceSource ("Dequeue",
+                     "A  (data) packet was passed down to PHY from MAC",
+                     MakeTraceSourceAccessor (&UanMacRc::m_dequeueLogger))
+    .AddTraceSource ("RX",
+                     "A packet was destined for and received at this MAC layer",
+                     MakeTraceSourceAccessor (&UanMacRc::m_rxLogger))
+  ;
+  return tid;
+}
+
+
+Address
+UanMacRc::GetAddress (void)
+{
+  return m_address;
+}
+
+void
+UanMacRc::SetAddress (UanAddress addr)
+{
+  m_address = addr;
+}
+
+bool
+UanMacRc::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
+{
+  if (protocolNumber > 0)
+    {
+      NS_LOG_WARN ("Warning: UanMacRc does not support multiple protocols.  protocolNumber argument to Enqueue is being ignored");
+    }
+
+
+  if (m_pktQueue.size () >= m_queueLimit)
+    {
+      return false;
+    }
+
+  m_pktQueue.push_back (std::make_pair (packet, UanAddress::ConvertFrom (dest)));
+
+  switch (m_state)
+    {
+    case UNASSOCIATED:
+      Associate ();
+      return true;
+    case IDLE:
+      if (!m_rtsEvent.IsRunning ())
+        {
+          SendRts ();
+        }
+      return true;
+    case GWPSENT:
+    case RTSSENT:
+    case DATATX:
+      return true;
+    }
+
+  return true;
+}
+
+void
+UanMacRc::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb)
+{
+  m_forwardUpCb = cb;
+}
+
+void
+UanMacRc::AttachPhy (Ptr<UanPhy> phy)
+{
+  m_phy = phy;
+  m_phy->SetReceiveOkCallback (MakeCallback (&UanMacRc::ReceiveOkFromPhy, this));
+}
+
+Address
+UanMacRc::GetBroadcast (void) const
+{
+  return UanAddress::GetBroadcast ();
+}
+
+void
+UanMacRc::ReceiveOkFromPhy (Ptr<Packet> pkt, double sinr, UanTxMode mode)
+{
+
+  UanHeaderCommon ch;
+  pkt->RemoveHeader (ch);
+  if (ch.GetDest () == m_address || ch.GetDest () == UanAddress::GetBroadcast ())
+    {
+      m_rxLogger (pkt, mode);
+    }
+
+  switch (ch.GetType ())
+    {
+    case TYPE_DATA:
+
+      if (ch.GetDest () == m_address)
+        {
+          NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " UanMacRc Receiving DATA packet from PHY");
+          UanHeaderRcData dh;
+          pkt->RemoveHeader (dh);
+          m_forwardUpCb (pkt, ch.GetSrc ());
+        }
+      break;
+    case TYPE_RTS:
+      // Currently don't respond to RTS packets at non-gateway nodes
+      // (Code assumes single network neighberhood)
+      break;
+    case TYPE_CTS:
+      {
+        uint32_t ctsBytes = ch.GetSerializedSize () + pkt->GetSize ();
+        m_assocAddr = ch.GetSrc ();
+        UanHeaderRcCtsGlobal ctsg;
+        pkt->RemoveHeader (ctsg);
+        m_currentRate = ctsg.GetRateNum ();
+        m_retryRate = m_minRetryRate + m_retryStep*ctsg.GetRetryRate ();
+
+        UanHeaderRcRts rhtmp;
+
+        Time winDelay = ctsg.GetWindowTime ();
+
+        if (winDelay.GetSeconds () > 0)
+          {
+            m_rtsBlocked = false;
+            Simulator::Schedule (winDelay, &UanMacRc::BlockRtsing, this);
+          }
+        else
+          {
+            NS_FATAL_ERROR (Simulator::Now ().GetSeconds () << " Node " << m_address << " Received window period < 0");
+          }
+
+        UanHeaderRcCts ctsh;
+        ctsh.SetAddress (UanAddress::GetBroadcast ());
+        while (pkt->GetSize () > 0)
+          {
+            pkt->RemoveHeader (ctsh);
+            if (ctsh.GetAddress () == m_address)
+              {
+                if (m_state == GWPSENT)
+                  {
+                    m_assocAddr = ch.GetSrc ();
+                    ScheduleData (ctsh, ctsg, ctsBytes);
+                  }
+                else if (m_state == RTSSENT)
+                  {
+                    ScheduleData (ctsh, ctsg, ctsBytes);
+                  }
+                else
+                  {
+                    NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS while state != RTSSENT or GWPING");
+                  }
+              }
+          }
+      }
+      break;
+    case TYPE_GWPING:
+      // Do not respond to GWPINGS at non-gateway nodes
+      break;
+    case TYPE_ACK:
+      m_rtsBlocked = true;
+      if (ch.GetDest () != m_address)
+        {
+          return;
+        }
+      ProcessAck (pkt);
+      break;
+    default:
+      NS_FATAL_ERROR ("Unknown packet type " << ch.GetType () << " received at node " << GetAddress ());
+    }
+
+}
+
+void
+UanMacRc::ScheduleData (const UanHeaderRcCts &ctsh, const UanHeaderRcCtsGlobal &ctsg, uint32_t ctsBytes)
+{
+  NS_ASSERT (m_state == RTSSENT || m_state == GWPSENT);
+
+
+
+  std::list<Reservation>::iterator it = m_resList.begin ();
+  for (; it != m_resList.end (); it++)
+    {
+      if (it->GetFrameNo () == ctsh.GetFrameNo ())
+        {
+          break;
+        }
+    }
+  if (it == m_resList.end ())
+    {
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS packet with no corresponding reservation!");
+      return;
+    }
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS packet.  Scheduling data");
+  it->SetTransmitted ();
+
+  double currentBps = m_phy->GetMode (m_currentRate).GetDataRateBps ();
+
+  m_learnedProp = Simulator::Now () - ctsg.GetTxTimeStamp () - Seconds (ctsBytes * 8.0 / currentBps);
+
+
+  Time arrTime = ctsg.GetTxTimeStamp () + ctsh.GetDelayToTx ();
+  Time txTime = arrTime - m_learnedProp;
+
+  Time startDelay = txTime - Simulator::Now ();
+
+  Time frameDelay = Seconds (0);
+
+  const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList ();
+  std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit;
+  pit = l.begin ();
+
+
+
+  for (uint32_t i = 0; i < it->GetNoFrames (); i++, pit++)
+    {
+      Ptr<Packet> pkt = (*pit).first->Copy ();
+
+      UanHeaderRcData dh;
+      dh.SetFrameNo (i);
+      dh.SetPropDelay (m_learnedProp);
+      pkt->AddHeader (dh);
+
+      UanHeaderCommon ch;
+      ch.SetType (TYPE_DATA);
+      ch.SetDest (m_assocAddr);
+      ch.SetSrc (m_address);
+
+      pkt->AddHeader (ch);
+      Time eventTime = startDelay + frameDelay;
+      if (eventTime.GetSeconds () < 0)
+        {
+          if (eventTime.GetSeconds () > -0.001)
+            {
+              eventTime = Seconds (0);
+            }
+          else
+            {
+              NS_FATAL_ERROR ("Scheduling error resulted in very negative data transmission time! eventTime = " << eventTime.GetSeconds ());
+            }
+        }
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " scheduling with delay " << eventTime.GetSeconds () << " propDelay " << m_learnedProp.GetSeconds () << " start delay " << startDelay.GetSeconds () << " arrival time " << arrTime.GetSeconds ());
+      Simulator::Schedule (eventTime, &UanMacRc::SendPacket, this, pkt, m_currentRate);
+      frameDelay = frameDelay + m_sifs + Seconds (pkt->GetSize () / currentBps);
+    }
+
+  m_state = IDLE;
+  if (!m_pktQueue.empty ())
+    {
+
+      if (m_rtsEvent.IsRunning ())
+        {
+          m_rtsEvent.Cancel ();
+        }
+      ExponentialVariable ev (1 / m_retryRate);
+      double timeout = ev.GetValue ();
+      m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::SendRts, this);
+    }
+
+}
+
+void
+UanMacRc::SendPacket (Ptr<Packet> pkt, uint32_t rate)
+{
+  UanHeaderCommon ch;
+  pkt->PeekHeader (ch);
+  std::string type;
+  switch (ch.GetType ())
+    {
+    case TYPE_DATA:
+      type = "DATA";
+      break;
+    case TYPE_RTS:
+      type = "RTS";
+      break;
+    case TYPE_CTS:
+      type = "CTS";
+      break;
+    case TYPE_ACK:
+      type = "ACK";
+      break;
+    case TYPE_GWPING:
+      type = "GWPING";
+      break;
+    default:
+      type = "UNKNOWN";
+      break;
+    }
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " transmitting " << pkt->GetSize () << " byte packet of type " << type << " with rate " << rate << "(" << m_phy->GetMode (rate).GetDataRateBps () << ") to " << ch.GetDest ());
+  m_dequeueLogger (pkt, rate);
+  m_phy->SendPacket (pkt, rate);
+}
+
+void
+UanMacRc::ProcessAck (Ptr<Packet> ack)
+{
+  UanHeaderRcAck ah;
+  ack->RemoveHeader (ah);
+
+  std::list<Reservation>::iterator it = m_resList.begin ();
+  for (; it != m_resList.end (); it++)
+    {
+      if (it->GetFrameNo () == ah.GetFrameNo ())
+        {
+          break;
+        }
+    }
+  if (it == m_resList.end ())
+    {
+      NS_LOG_DEBUG ("In " << __func__ << " could not find reservation corresponding to received ACK");
+      return;
+    }
+  if (!it->IsTransmitted ())
+    {
+      return;
+    }
+  if (ah.GetNoNacks () > 0)
+    {
+      const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList ();
+      std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit;
+      pit = l.begin ();
+
+      const std::set<uint8_t> &nacks = ah.GetNackedFrames ();
+      std::set<uint8_t>::iterator nit = nacks.begin ();
+      uint8_t pnum = 0;
+      for (; nit != nacks.end (); nit++)
+        {
+          NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " Received NACK for " << (uint32_t) *nit);
+          while (pnum < *nit)
+            {
+              pit++;
+              pnum++;
+            }
+          UanHeaderRcData dh;
+          UanHeaderCommon ch;
+          m_pktQueue.push_front (*pit);
+        }
+    }
+  else
+    {
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received ACK for all frames");
+    }
+  m_resList.erase (it);
+}
+
+UanHeaderRcRts
+UanMacRc::CreateRtsHeader (const Reservation &res)
+{
+  UanHeaderRcRts rh = UanHeaderRcRts ();
+
+  rh.SetLength (res.GetLength ());
+  rh.SetNoFrames (res.GetNoFrames ());
+  rh.SetTimeStamp (res.GetTimestamp (res.GetRetryNo ()));
+  rh.SetFrameNo (res.GetFrameNo ());
+  rh.SetRetryNo (res.GetRetryNo ());
+  return rh;
+}
+
+void
+UanMacRc::Associate (void)
+{
+  m_cntrlSends++;
+
+  Reservation res (m_pktQueue, m_frameNo, m_maxFrames);
+  res.AddTimestamp (Simulator::Now ());
+  m_frameNo++;
+  m_resList.push_back (res);
+  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
+  bool phy1ok = IsPhy1Ok ();
+  if (phy1ok && !phyDual->IsPhy2Tx () & !m_rtsBlocked)
+    {
+      Ptr<Packet> pkt = Create<Packet> (0);
+      pkt->AddHeader (CreateRtsHeader (res));
+      pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_GWPING));
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending first GWPING " << *pkt);
+      SendPacket (pkt,m_currentRate + m_numRates);
+    }
+  m_state = GWPSENT;
+  NS_ASSERT (!m_rtsEvent.IsRunning ());
+  ExponentialVariable ev (1.0 / m_retryRate);
+  double timeout = ev.GetValue ();
+  m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::AssociateTimeout, this);
+}
+
+void
+UanMacRc::AssociateTimeout ()
+{
+  m_cntrlSends++;
+  if (m_state != GWPSENT)
+    {
+      return;
+    }
+  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
+  bool phy1ok = IsPhy1Ok ();
+  if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked)
+    {
+      Ptr<Packet> pkt = Create<Packet> ();
+
+      Reservation res = m_resList.back ();
+      m_resList.pop_back ();
+      res.AddTimestamp (Simulator::Now ());
+      res.IncrementRetry ();
+
+      pkt->AddHeader (CreateRtsHeader (res));
+      pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_GWPING));
+
+      SendPacket (pkt,m_currentRate + m_numRates);
+      m_resList.push_back (res);
+    }
+  NS_ASSERT (!m_rtsEvent.IsRunning ());
+  ExponentialVariable ev (1.0 / m_retryRate);
+  double timeout = ev.GetValue ();
+  m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::AssociateTimeout, this);
+}
+
+
+void
+UanMacRc::SendRts (void)
+{
+  m_cntrlSends++;
+  if (m_state == RTSSENT)
+    {
+      return;
+    }
+
+  NS_ASSERT (!m_pktQueue.empty ());
+
+  Reservation res (m_pktQueue, m_frameNo, m_maxFrames);
+  res.AddTimestamp (Simulator::Now ());
+  m_frameNo++;
+  m_resList.push_back (res);
+  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
+  bool phy1ok = IsPhy1Ok ();
+  if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked )
+    {
+      Ptr<Packet> pkt = Create<Packet> (0);
+      pkt->AddHeader (CreateRtsHeader (res));
+      pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_RTS));
+      SendPacket (pkt,m_currentRate + m_numRates);
+    }
+  m_state = RTSSENT;
+  NS_ASSERT (!m_rtsEvent.IsRunning ());
+  ExponentialVariable ev (1.0 / m_retryRate);
+  double timeout = ev.GetValue ();
+  m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::RtsTimeout, this);
+
+}
+
+// We assume here that packet types are known at detection.
+bool
+UanMacRc::IsPhy1Ok ()
+{
+  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
+
+  bool phy1ok = true;
+  if (phyDual->IsPhy1Rx ())
+    {
+      Ptr<Packet> pkt = phyDual->GetPhy1PacketRx ();
+      UanHeaderCommon ch;
+      pkt->PeekHeader (ch);
+      if (ch.GetType () == TYPE_CTS || ch.GetType () == TYPE_ACK)
+        {
+          phy1ok = false;
+        }
+      else if (ch.GetDest () == m_address)
+        {
+          phy1ok = false;
+        }
+    }
+  return phy1ok;
+}
+
+void
+UanMacRc::RtsTimeout (void)
+{
+  m_cntrlSends++;
+
+  if (m_state != RTSSENT)
+    {
+      return;
+    }
+  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
+
+  bool phy1ok = IsPhy1Ok ();
+  if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked)
+    {
+
+      if (m_resList.empty ())
+        {
+          NS_FATAL_ERROR (Simulator::Now ().GetSeconds () << " Node " << m_address << " tried to retry RTS with empty reservation list");
+        }
+      Ptr<Packet> pkt = Create<Packet> (0);
+
+      Reservation res = m_resList.back ();
+      NS_ASSERT (!res.IsTransmitted ());
+      m_resList.pop_back ();
+      res.AddTimestamp (Simulator::Now ());
+      res.IncrementRetry ();
+      m_resList.push_back (res);
+      pkt->AddHeader (CreateRtsHeader (res));
+      pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_RTS));
+      SendPacket (pkt,m_currentRate + m_numRates);
+
+    }
+  m_state = RTSSENT;
+  NS_ASSERT (!m_rtsEvent.IsRunning ());
+  ExponentialVariable ev (1.0 / m_retryRate);
+  double timeout = ev.GetValue ();
+  m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::RtsTimeout, this);
+}
+
+void 
+UanMacRc::BlockRtsing (void)
+{
+  m_rtsBlocked = true;
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac-rc.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,221 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANMACRC_H
+#define UANMACRC_H
+
+#include "uan-mac.h"
+#include "uan-address.h"
+
+#include "ns3/nstime.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/traced-callback.h"
+#include "ns3/event-id.h"
+
+#include <list>
+#include <utility>
+#include <vector>
+
+
+namespace ns3 {
+
+class Address;
+
+namespace uan {
+
+class UanTxMode;
+class UanHeaderRcRts;
+class UanHeaderRcCts;
+class UanHeaderRcCtsGlobal;
+class UanPhy;
+
+
+/**
+ * \class Reservation
+ * \brief Stores reservation info for use in scheduling data channel by reservation channel MAC
+ */
+class Reservation
+{
+public:
+  /**
+   * \brief Create empty object with default values
+   */
+  Reservation ();
+  /**
+   * \brief Create Reservation object with given packet list, frame number and max packets
+   * \param list List of packets for assigned to reservation
+   * \param frameNo Frame number of reservation transmission
+   * \param maxPkts Maximum number of packets to assign to reservation from packet list (0 = no maximum)
+   */
+  Reservation (std::list<std::pair <Ptr<Packet>, UanAddress > > &list, uint8_t frameNo, uint32_t maxPkts = 0);
+  ~Reservation ();
+  /**
+   * \returns number of frames in reservation
+   */
+  uint32_t GetNoFrames () const;
+  /**
+   * \returns total byte length of reservation (sum of all packets with headers)
+   */
+  uint32_t GetLength () const;
+  /**
+   * \returns reference to list of packets in this reservation
+   */
+  const std::list<std::pair <Ptr<Packet>, UanAddress > > &GetPktList (void) const;
+  /**
+   * \returns Frame number of reservation
+   */
+  uint8_t GetFrameNo () const;
+  /**
+   * \returns Retry number of reservation
+   */
+  uint8_t GetRetryNo () const;
+  /**
+   * \returns Timestamp nth RTS send for this reservation
+   * \param n Timestamp for retry number n to return
+   */
+  Time GetTimestamp (uint8_t n) const;
+  /**
+   * \returns True if reservation packets have been transmitted
+   */
+  bool IsTransmitted () const;
+  /**
+   * \param fn Frame number to set reservation to
+   */
+  void SetFrameNo (uint8_t fn);
+  /**
+   * \param t Time of latest RTS send
+   */
+  void AddTimestamp (Time t);
+  /**
+   * \brief Increments retry count by 1
+   */
+  void IncrementRetry ();
+  /**
+   * \param t True if resevation has been transmitted
+   * \brief Sets reservation transmitted state
+   */
+  void SetTransmitted (bool t = true);
+private:
+  std::list<std::pair <Ptr<Packet>, UanAddress > > m_pktList;
+  uint32_t m_length;
+  uint8_t m_frameNo;
+  std::vector<Time> m_timestamp;
+  uint8_t m_retryNo;
+  bool m_transmitted;
+
+};
+
+
+/**
+ * \class UanMacRc
+ * \brief Non-gateway node MAC for reservation channel MAC protocol
+ *
+ * This MAC protocol assumes a network topology where all traffic
+ * is destined for a set of GW nodes which are connected via
+ * some out of band (RF?) means.  This particular implementation
+ * assumes that there is only a single gateway.
+ *
+ * For more information on class operation email
+ * lentracy@u.washington.edu
+ * (This work is, as of yet, unpublished)
+ */
+class UanMacRc : public UanMac
+{
+public:
+  enum {
+    TYPE_DATA, TYPE_GWPING, TYPE_RTS, TYPE_CTS, TYPE_ACK
+  };
+  UanMacRc ();
+  virtual ~UanMacRc ();
+
+  static TypeId GetTypeId (void);
+
+  // Inherited virtual functions
+  virtual Address GetAddress (void);
+  virtual void SetAddress (UanAddress addr);
+  virtual bool Enqueue (Ptr<Packet> pkt, const Address &dest, uint16_t protocolNumber);
+  virtual void SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb);
+  virtual void AttachPhy (Ptr<UanPhy> phy);
+  virtual Address GetBroadcast (void) const;
+  virtual void Clear (void);
+
+private:
+  enum State {
+    UNASSOCIATED, GWPSENT, IDLE, RTSSENT, DATATX
+  };
+
+  State m_state;
+  bool m_rtsBlocked;
+
+  EventId m_startAgain;
+  UanAddress m_address;
+  double m_retryRate;
+  UanAddress m_assocAddr;
+  Ptr<UanPhy> m_phy;
+  uint32_t m_numRates;
+  uint32_t m_currentRate;
+  uint32_t m_maxFrames;
+  uint32_t m_queueLimit;
+  uint8_t m_frameNo;
+  Time m_sifs;
+  Time m_learnedProp;
+
+  uint16_t m_numRetryRates;
+  double m_minRetryRate;
+  double m_retryStep;
+
+  uint32_t m_ctsSizeN;
+  uint32_t m_ctsSizeG;
+
+  bool m_cleared;
+
+  std::list<std::pair <Ptr<Packet>, UanAddress > > m_pktQueue;
+  std::list<Reservation> m_resList;
+
+  Callback<void, Ptr<Packet>, const UanAddress& > m_forwardUpCb;
+
+  TracedCallback<Ptr<const Packet>, UanTxMode > m_rxLogger;
+  TracedCallback<Ptr<const Packet>, uint16_t > m_enqueueLogger;
+  TracedCallback<Ptr<const Packet>, uint16_t > m_dequeueLogger;
+
+  EventId m_rtsEvent;
+  void ReceiveOkFromPhy (Ptr<Packet>, double sinr, UanTxMode mode);
+
+  void Associate (void);
+  void AssociateTimeout (void);
+  void SendRts (void);
+  void RtsTimeout (void);
+  UanHeaderRcRts CreateRtsHeader (const Reservation &res);
+  void ScheduleData (const UanHeaderRcCts &ctsh, const UanHeaderRcCtsGlobal &ctsg, uint32_t ctsBytes);
+  void ProcessAck (Ptr<Packet> ack);
+  void SendPacket (Ptr<Packet> pkt, uint32_t rate);
+  bool IsPhy1Ok (void);
+  void BlockRtsing (void);
+
+  static uint32_t m_cntrlSends;
+
+protected:
+  void DoDispose ();
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANMACRC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-mac.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,98 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANMAC_H
+#define UANMAC_H
+
+#include "ns3/address.h"
+#include "ns3/object.h"
+#include "ns3/packet.h"
+
+#include "ns3/address.h"
+#include "ns3/nstime.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+namespace uan {
+
+class UanPhy;
+class UanChannel;
+class UanNetDevice;
+class UanTransducer;
+class UanAddress;
+
+
+
+/**
+ * \class UanMac
+ *
+ * \brief Virtual base class for all UAN MAC protocols
+ */
+class UanMac : public Object
+{
+public:
+  /**
+   * \returns MAC Address
+   */
+  virtual Address GetAddress (void) = 0;
+
+  /**
+   * \param addr UanAddress for this MAC
+   */
+  virtual void SetAddress (UanAddress addr) = 0;
+
+  /**
+   * Enqueue packet to be transmitted
+   * \param pkt Packet to be transmitted
+   * \param dest Destination address
+   * \param protocolNumber Protocol #.  Usage varies by MAC
+   */
+  virtual bool Enqueue (Ptr<Packet> pkt, const Address &dest, uint16_t protocolNumber) = 0;
+  /**
+   * \param cb  Callback to be called when a packet is forwarded up to higher layer
+   */
+  virtual void SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb) = 0;
+
+  /**
+   * Attach PHY layer to this MAC.
+   * Some MACs may be designed to work with multiple PHY
+   * layers.  Others may only work with one.
+   *
+   * \param phy Phy layer to attach to this MAC
+   *
+   */
+  virtual void AttachPhy (Ptr<UanPhy> phy) = 0;
+
+  /**
+   * \returns Broadcast address
+   */
+  virtual Address GetBroadcast (void) const = 0;
+
+  /**
+   * Clears all pointer references
+   */
+  virtual void Clear (void) = 0;
+
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANMAC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-module.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,32 @@
+
+#ifdef NS3_MODULE_COMPILATION
+# error "Do not include ns3 module aggregator headers from other modules; these are meant only for end user scripts."
+#endif
+
+#ifndef NS3_MODULE_UAN
+    
+
+// Module headers:
+#include "uan-address.h"
+#include "uan-channel.h"
+#include "uan-header-common.h"
+#include "uan-header-rc.h"
+#include "uan-helper.h"
+#include "uan-mac-aloha.h"
+#include "uan-mac-cw.h"
+#include "uan-mac-rc-gw.h"
+#include "uan-mac-rc.h"
+#include "uan-mac.h"
+#include "uan-net-device.h"
+#include "uan-noise-model-default.h"
+#include "uan-noise-model.h"
+#include "uan-phy-dual.h"
+#include "uan-phy-gen.h"
+#include "uan-phy.h"
+#include "uan-prop-model-ideal.h"
+#include "uan-prop-model-thorp.h"
+#include "uan-prop-model.h"
+#include "uan-transducer-hd.h"
+#include "uan-transducer.h"
+#include "uan-tx-mode.h"
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-net-device.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,395 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "ns3/trace-source-accessor.h"
+#include "ns3/traced-callback.h"
+#include "ns3/pointer.h"
+#include "ns3/node.h"
+#include "ns3/assert.h"
+#include "uan-net-device.h"
+#include "uan-phy.h"
+#include "uan-mac.h"
+#include "uan-channel.h"
+#include "uan-transducer.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("UanNetDevice");
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanNetDevice);
+
+UanNetDevice::UanNetDevice ()
+  : NetDevice (),
+    m_mtu (64000),
+    m_cleared (false)
+{
+}
+
+UanNetDevice::~UanNetDevice ()
+{
+}
+
+void
+UanNetDevice::Clear ()
+{
+  if (m_cleared)
+    {
+      return;
+    }
+  m_cleared = true;
+  m_node = 0;
+  if (m_channel)
+    {
+      m_channel->Clear ();
+      m_channel = 0;
+    }
+  if (m_mac)
+    {
+      m_mac->Clear ();
+      m_mac = 0;
+    }
+  if (m_phy)
+    {
+      m_phy->Clear ();
+      m_phy = 0;
+    }
+  if (m_trans)
+    {
+      m_trans->Clear ();
+      m_trans = 0;
+    }
+}
+
+void
+UanNetDevice::DoDispose ()
+{
+  Clear ();
+  NetDevice::DoDispose ();
+}
+
+TypeId
+UanNetDevice::GetTypeId ()
+{
+
+
+  static TypeId tid = TypeId ("ns3::UanNetDevice")
+    .SetParent<NetDevice> ()
+    .AddAttribute ("Channel", "The channel attached to this device",
+                   PointerValue (),
+                   MakePointerAccessor (&UanNetDevice::DoGetChannel, &UanNetDevice::SetChannel),
+                   MakePointerChecker<UanChannel> ())
+    .AddAttribute ("Phy", "The PHY layer attached to this device.",
+                   PointerValue (),
+                   MakePointerAccessor (&UanNetDevice::GetPhy, &UanNetDevice::SetPhy),
+                   MakePointerChecker<UanPhy> ())
+    .AddAttribute ("Mac", "The MAC layer attached to this device.",
+                   PointerValue (),
+                   MakePointerAccessor (&UanNetDevice::GetMac, &UanNetDevice::SetMac),
+                   MakePointerChecker<UanMac> ())
+    .AddAttribute ("Transducer", "The Transducer attached to this device.",
+                   PointerValue (),
+                   MakePointerAccessor (&UanNetDevice::GetTransducer,
+                                        &UanNetDevice::SetTransducer),
+                   MakePointerChecker<UanTransducer> ())
+    .AddTraceSource ("Rx", "Received payload from the MAC layer.",
+                     MakeTraceSourceAccessor (&UanNetDevice::m_rxLogger))
+    .AddTraceSource ("Tx", "Send payload to the MAC layer.",
+                     MakeTraceSourceAccessor (&UanNetDevice::m_txLogger))
+  ;
+  return tid;
+}
+
+void
+UanNetDevice::SetMac (Ptr<UanMac> mac)
+{
+  if (mac != 0)
+    {
+      m_mac = mac;
+      NS_LOG_DEBUG ("Set MAC");
+
+      if (m_phy != 0)
+        {
+          m_phy->SetMac (mac);
+          m_mac->AttachPhy (m_phy);
+          NS_LOG_DEBUG ("Attached MAC to PHY");
+        }
+      m_mac->SetForwardUpCb (MakeCallback (&UanNetDevice::ForwardUp, this));
+    }
+
+}
+
+void
+UanNetDevice::SetPhy (Ptr<UanPhy> phy)
+{
+  if (phy != 0)
+    {
+      m_phy = phy;
+      m_phy->SetDevice (Ptr<UanNetDevice> (this));
+      NS_LOG_DEBUG ("Set PHY");
+      if (m_mac != 0)
+        {
+          m_mac->AttachPhy (phy);
+          m_phy->SetMac (m_mac);
+          NS_LOG_DEBUG ("Attached PHY to MAC");
+        }
+      if (m_trans != 0)
+        {
+          m_phy->SetTransducer (m_trans);
+          NS_LOG_DEBUG ("Added PHY to trans");
+        }
+
+    }
+}
+
+void
+UanNetDevice::SetChannel (Ptr<UanChannel> channel)
+{
+  if (channel != 0)
+    {
+      m_channel = channel;
+      NS_LOG_DEBUG ("Set CHANNEL");
+      if (m_trans != 0)
+        {
+
+          m_channel->AddDevice (this, m_trans);
+          NS_LOG_DEBUG ("Added self to channel device list");
+          m_trans->SetChannel (m_channel);
+          NS_LOG_DEBUG ("Set Transducer channel");
+        }
+      if (m_phy != 0 )
+        {
+          m_phy->SetChannel (channel);
+        }
+    }
+}
+
+Ptr<UanChannel>
+UanNetDevice::DoGetChannel (void) const
+{
+  return m_channel;
+
+}
+Ptr<UanMac>
+UanNetDevice::GetMac () const
+{
+  return m_mac;
+}
+
+Ptr<UanPhy>
+UanNetDevice::GetPhy () const
+{
+  return m_phy;
+}
+
+void
+UanNetDevice::SetIfIndex (uint32_t index)
+{
+  m_ifIndex = index;
+}
+
+uint32_t
+UanNetDevice::GetIfIndex () const
+{
+  return m_ifIndex;
+}
+
+Ptr<Channel>
+UanNetDevice::GetChannel () const
+{
+  return m_channel;
+}
+
+Address
+UanNetDevice::GetAddress () const
+{
+  return m_mac->GetAddress ();
+}
+
+bool
+UanNetDevice::SetMtu (uint16_t mtu)
+{
+  // TODO:  Check this in MAC
+  NS_LOG_WARN ("UanNetDevice:  MTU is not implemented");
+  m_mtu = mtu;
+  return true;
+}
+
+uint16_t
+UanNetDevice::GetMtu () const
+{
+  return m_mtu;
+}
+
+bool
+UanNetDevice::IsLinkUp () const
+{
+  return  (m_linkup && (m_phy != 0));
+}
+
+bool
+UanNetDevice::IsBroadcast () const
+{
+  return true;
+}
+
+Address
+UanNetDevice::GetBroadcast () const
+{
+  return m_mac->GetBroadcast ();
+}
+
+bool
+UanNetDevice::IsMulticast () const
+{
+  return false;
+}
+
+Address
+UanNetDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+  NS_FATAL_ERROR ("UanNetDevice does not support multicast");
+  return m_mac->GetBroadcast ();
+}
+
+Address
+UanNetDevice::GetMulticast (Ipv6Address addr) const
+{
+  NS_FATAL_ERROR ("UanNetDevice does not support multicast");
+  return m_mac->GetBroadcast ();
+}
+
+bool
+UanNetDevice::IsBridge (void) const
+{
+  return false;
+}
+bool
+UanNetDevice::IsPointToPoint () const
+{
+  return false;
+}
+
+bool
+UanNetDevice::Send (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
+{
+  return m_mac->Enqueue (packet, dest, protocolNumber);
+}
+
+bool
+UanNetDevice::SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
+{
+  // Not yet implemented
+  NS_ASSERT_MSG (0, "Not yet implemented");
+  return false;
+}
+Ptr<Node>
+UanNetDevice::GetNode () const
+{
+  return m_node;
+}
+
+void
+UanNetDevice::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+bool
+UanNetDevice::NeedsArp () const
+{
+  return false;
+}
+
+void
+UanNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_forwardUp = cb;
+}
+
+void
+UanNetDevice::ForwardUp (Ptr<Packet> pkt, const UanAddress &src)
+{
+  NS_LOG_DEBUG ("Forwarding packet up to application");
+  m_rxLogger (pkt, src);
+  m_forwardUp (this, pkt, 0, src);
+
+}
+
+Ptr<UanTransducer>
+UanNetDevice::GetTransducer (void) const
+{
+  return m_trans;
+}
+void
+UanNetDevice::SetTransducer (Ptr<UanTransducer> trans)
+{
+
+  if (trans != 0)
+    {
+      m_trans = trans;
+      NS_LOG_DEBUG ("Set Transducer");
+      if (m_phy != 0)
+        {
+          m_phy->SetTransducer (m_trans);
+          NS_LOG_DEBUG ("Attached Phy to transducer");
+        }
+
+      if (m_channel != 0)
+        {
+          m_channel->AddDevice (this, m_trans);
+          m_trans->SetChannel (m_channel);
+          NS_LOG_DEBUG ("Added self to channel device list");
+        }
+    }
+
+}
+
+void
+UanNetDevice::AddLinkChangeCallback (Callback<void> callback)
+{
+  m_linkChanges.ConnectWithoutContext (callback);
+}
+
+
+void
+UanNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
+{
+  // Not implemented yet
+  NS_ASSERT_MSG (0, "Not yet implemented");
+}
+
+bool
+UanNetDevice::SupportsSendFrom (void) const
+{
+  return false;
+}
+
+void
+UanNetDevice::SetAddress (Address address)
+{
+  NS_ASSERT_MSG (0, "Tried to set MAC address with no MAC");
+  m_mac->SetAddress (UanAddress::ConvertFrom (address));
+}
+
+} // namespace uan
+} // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-net-device.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,153 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANNETDEVICE_H
+#define UANNETDEVICE_H
+
+#include "ns3/net-device.h"
+#include "ns3/pointer.h"
+#include "ns3/traced-callback.h"
+#include "uan-address.h"
+#include <list>
+
+namespace ns3 {
+namespace uan {
+
+class UanChannel;
+class UanPhy;
+class UanMac;
+class UanTransducer;
+
+/**
+ * \class UanNetDevice
+ *
+ * \brief Net device for UAN models
+ */
+class UanNetDevice : public NetDevice
+{
+public:
+  /**
+   * \brief UanPhyList is defined as a standard template lib list of UanPhy objects
+   */
+  typedef std::list<Ptr<UanPhy> > UanPhyList;
+  /**
+   * \brief UanTransducerList is a standard template lib list of UanTransducer objects
+   */
+  typedef std::list<Ptr<UanTransducer> > UanTransducerList;
+
+  static TypeId GetTypeId (void);
+
+  UanNetDevice ();
+  virtual ~UanNetDevice ();
+
+  /**
+   * \param mac Set MAC layer for this device
+   */
+  void SetMac (Ptr<UanMac> mac);
+
+  /**
+   * \param phy Set PHY layer for this device
+   */
+  void SetPhy (Ptr<UanPhy> phy);
+
+  /**
+   * \param channel The channel this device is attached to
+   */
+  void SetChannel (Ptr<UanChannel> channel);
+
+  /**
+   * \returns MAC this device is using
+   */
+  Ptr<UanMac> GetMac (void) const;
+
+  /**
+   * \returns PHY this device is using
+   */
+  Ptr<UanPhy> GetPhy (void) const;
+
+  /**
+   * \returns Transducer in net device
+   */
+  Ptr<UanTransducer> GetTransducer (void) const;
+  /**
+   * \param trans Transducer to use in this net device
+   */
+  void SetTransducer (Ptr<UanTransducer> trans);
+
+  /**
+   * Clears all pointer references
+   */
+  void Clear (void);
+
+  // Purely virtual functions from base class
+  virtual void SetIfIndex (const uint32_t index);
+  virtual uint32_t GetIfIndex (void) const;
+  virtual Ptr<Channel> GetChannel (void) const;
+  virtual Address GetAddress (void) const;
+  virtual bool SetMtu (const uint16_t mtu);
+  virtual uint16_t GetMtu (void) const;
+  virtual bool IsLinkUp (void) const;
+  virtual bool IsBroadcast (void) const;
+  virtual Address GetBroadcast (void) const;
+  virtual bool IsMulticast (void) const;
+  virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+  virtual Address GetMulticast (Ipv6Address addr) const;
+  virtual bool IsBridge (void) const ;
+  virtual bool IsPointToPoint (void) const;
+  virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
+  virtual Ptr<Node> GetNode (void) const;
+  virtual void SetNode (Ptr<Node> node);
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+  virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
+  virtual bool SupportsSendFrom (void) const;
+  virtual void AddLinkChangeCallback (Callback<void> callback);
+  virtual void SetAddress (Address address);
+private:
+  virtual void ForwardUp (Ptr<Packet> pkt, const UanAddress &src);
+  Ptr<UanChannel> DoGetChannel (void) const;
+
+  Ptr<UanTransducer> m_trans;
+  Ptr<Node> m_node;
+  Ptr<UanChannel> m_channel;
+  Ptr<UanMac> m_mac;
+  Ptr<UanPhy> m_phy;
+
+  std::string m_name;
+  uint32_t m_ifIndex;
+  uint16_t m_mtu;
+  bool m_linkup;
+  TracedCallback<> m_linkChanges;
+  ReceiveCallback m_forwardUp;
+
+  TracedCallback<Ptr<const Packet>, UanAddress> m_rxLogger;
+  TracedCallback<Ptr<const Packet>, UanAddress> m_txLogger;
+
+  bool m_cleared;
+
+protected:
+  virtual void DoDispose ();
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANNETDEVICE_H 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-noise-model-default.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,82 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-noise-model-default.h"
+#include "ns3/double.h"
+
+#include <cmath>
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanNoiseModelDefault);
+
+UanNoiseModelDefault::UanNoiseModelDefault ()
+{
+
+}
+
+UanNoiseModelDefault::~UanNoiseModelDefault ()
+{
+}
+
+TypeId
+UanNoiseModelDefault::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanNoiseModelDefault")
+    .SetParent<Object> ()
+    .AddConstructor<UanNoiseModelDefault> ()
+    .AddAttribute ("Wind", "Wind speed in m/s",
+                   DoubleValue (1),
+                   MakeDoubleAccessor (&UanNoiseModelDefault::m_wind),
+                   MakeDoubleChecker<double> (0))
+    .AddAttribute ("Shipping", "Shipping contribution to noise between 0 and 1",
+                   DoubleValue (0),
+                   MakeDoubleAccessor (&UanNoiseModelDefault::m_shipping),
+                   MakeDoubleChecker<double> (0,1))
+  ;
+  return tid;
+}
+
+// Common acoustic noise formulas.  These can be found
+// in "Priniciples of Underwater Sound" by Robert J. Urick
+double
+UanNoiseModelDefault::GetNoiseDbHz (double fKhz) const
+{
+  double turb, win, ship, thermal, noise;
+  turb = 17.0 - 30.0 * log10 (fKhz);
+  turb = pow (10.0, turb * 0.1);
+
+  ship = 40.0 + 20.0 * (m_shipping - 0.5) + 26.0 * log10 (fKhz) - 60.0 * log10 (fKhz + 0.03);
+  ship = pow (10.0, (ship * 0.1));
+
+  win = 50.0 + 7.5 * pow (m_wind, 0.5) + 20.0 * log10 (fKhz) - 40.0 * log10 (fKhz + 0.4);
+  win = pow (10.0, m_wind * 0.1);
+
+  thermal = -15 + 20 * log10 (fKhz);
+  thermal = pow (10, thermal * 0.1);
+
+  noise = 10 * log10 (turb + ship + win + thermal);
+
+  return noise;
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-noise-model-default.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,68 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANNOISEMODELDEFAULT_H
+#define UANNOISEMODELDEFAULT_H
+
+#include "uan-noise-model.h"
+#include "ns3/attribute.h"
+#include "ns3/object.h"
+
+namespace ns3 {
+namespace uan {
+
+/**
+ * \class UanNoiseModelDefault
+ *
+ * Standard ambient acoustic noise model.  See attributes for parameters
+ *
+ * This class returns ambient noise by following the algorithm given in
+ * Harris, A. F. and Zorzi, M. 2007. Modeling the underwater acoustic channel in ns2.
+ * In Proceedings of the 2nd international Conference on Performance Evaluation
+ * Methodologies and Tools (Nantes, France, October 22 - 27, 2007). ValueTools,
+ * vol. 321. ICST (Institute for Computer Sciences Social-Informatics and
+ * Telecommunications Engineering), ICST, Brussels, Belgium, 1-8.
+ *
+ * Which uses the noise model also given in the book
+ * "Principles of Underwater Sound" by Urick
+ */
+class UanNoiseModelDefault : public UanNoiseModel
+{
+public:
+  UanNoiseModelDefault ();
+  virtual ~UanNoiseModelDefault ();
+
+  static TypeId GetTypeId (void);
+  /**
+   * \returns Noise power in dB re 1uPa/Hz
+   * \param fKhz Frequency in kHz
+   */
+  virtual double GetNoiseDbHz (double fKhz) const;
+
+private:
+  double m_wind;
+  double m_shipping;
+
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANNOISEMODELDEFAULT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-noise-model.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,41 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-noise-model.h"
+
+namespace ns3 {
+namespace uan {
+
+void 
+UanNoiseModel::Clear (void)
+{
+}
+
+void 
+UanNoiseModel::DoDispose (void)
+{
+  Clear ();
+  Object::DoDispose ();
+}
+
+
+
+} // namespace uan
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-noise-model.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,49 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANNOISEMODEL_H
+#define UANNOISEMODEL_H
+
+#include "ns3/object.h"
+
+namespace ns3 {
+namespace uan {
+
+class UanNoiseModel : public Object
+{
+public:
+  /**
+   * \param fKhz Frequency in kHz
+   * \returns Noise power in dB re 1uPa/Hz
+   */
+  virtual double GetNoiseDbHz (double fKhz) const = 0;
+
+  /**
+   * Clears all pointer references
+   */
+  virtual void Clear (void);
+
+  virtual void DoDispose (void);
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANNOISEMODEL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-phy-dual.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,651 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-phy.h"
+#include "uan-phy-dual.h"
+#include "uan-phy-gen.h"
+#include "uan-tx-mode.h"
+#include "uan-net-device.h"
+#include "uan-channel.h"
+#include "ns3/double.h"
+#include "ns3/log.h"
+#include "ns3/ptr.h"
+#include "ns3/traced-callback.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/simulator.h"
+#include "uan-header-common.h"
+#include "uan-mac-rc.h"
+
+#include <cmath>
+
+
+NS_LOG_COMPONENT_DEFINE ("UanPhyDual");
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanPhyDual);
+NS_OBJECT_ENSURE_REGISTERED (UanPhyCalcSinrDual);
+
+UanPhyCalcSinrDual::UanPhyCalcSinrDual ()
+{
+
+}
+UanPhyCalcSinrDual::~UanPhyCalcSinrDual ()
+{
+
+}
+
+TypeId
+UanPhyCalcSinrDual::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanPhyCalcSinrDual")
+    .SetParent<Object> ()
+    .AddConstructor<UanPhyCalcSinrDual> ()
+  ;
+  return tid;
+}
+
+double
+UanPhyCalcSinrDual::CalcSinrDb (Ptr<Packet> pkt,
+                                Time arrTime,
+                                double rxPowerDb,
+                                double ambNoiseDb,
+                                UanTxMode mode,
+                                UanPdp pdp,
+                                const UanTransducer::ArrivalList &arrivalList) const
+{
+
+  if (mode.GetModType () != UanTxMode::OTHER)
+    {
+      NS_LOG_WARN ("Calculating SINR for unsupported modulation type");
+    }
+
+  double intKp = -DbToKp (rxPowerDb); // This packet is in the arrivalList
+  UanTransducer::ArrivalList::const_iterator it = arrivalList.begin ();
+  for (; it != arrivalList.end (); it++)
+    {
+      // Only count interference if there is overlap in incoming frequency
+      if (std::abs ( (double) it->GetTxMode ().GetCenterFreqHz () - (double) mode.GetCenterFreqHz ())
+          < (double)(it->GetTxMode ().GetBandwidthHz () / 2 + mode.GetBandwidthHz () / 2) - 0.5)
+        {
+          UanHeaderCommon ch, ch2;
+          if (pkt)
+            {
+              pkt->PeekHeader (ch);
+            }
+          it->GetPacket ()->PeekHeader (ch2);
+
+          if (pkt)
+            {
+              if (ch.GetType () == UanMacRc::TYPE_DATA)
+                {
+                  NS_LOG_DEBUG ("Adding interferer from " << ch2.GetSrc () << " against " << ch.GetSrc () << ": PktRxMode: "
+                                                          << mode.GetName () << " Int mode: " << it->GetTxMode ().GetName () << " Separation: "
+                                                          << std::abs ( (double) it->GetTxMode ().GetCenterFreqHz () - (double) mode.GetCenterFreqHz ())
+                                                          << " Combined bandwidths: " << (double)(it->GetTxMode ().GetBandwidthHz () / 2 + mode.GetBandwidthHz () / 2) - 0.5);
+                }
+            }
+          intKp += DbToKp (it->GetRxPowerDb ());
+        }
+    }
+
+  double totalIntDb = KpToDb (intKp + DbToKp (ambNoiseDb));
+
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Calculating SINR:  RxPower = " << rxPowerDb << " dB.  Number of interferers = " << arrivalList.size () << "  Interference + noise power = " << totalIntDb << " dB.  SINR = " << rxPowerDb - totalIntDb << " dB.");
+  return rxPowerDb - totalIntDb;
+}
+
+UanPhyDual::UanPhyDual ()
+  :  UanPhy ()
+{
+
+  m_phy1 = CreateObject<UanPhyGen> ();
+  m_phy2 = CreateObject<UanPhyGen> ();
+
+  m_phy1->SetReceiveOkCallback (m_recOkCb);
+  m_phy2->SetReceiveOkCallback (m_recOkCb);
+
+  m_phy1->SetReceiveErrorCallback (m_recErrCb);
+  m_phy2->SetReceiveErrorCallback (m_recErrCb);
+
+}
+
+UanPhyDual::~UanPhyDual ()
+{
+}
+
+void
+UanPhyDual::Clear ()
+{
+  if (m_phy1)
+    {
+      m_phy1->Clear ();
+      m_phy1 = 0;
+    }
+  if (m_phy2)
+    {
+      m_phy2->Clear ();
+      m_phy2 = 0;
+    }
+}
+void
+UanPhyDual::DoDispose ()
+{
+  Clear ();
+  UanPhy::DoDispose ();
+}
+
+TypeId
+UanPhyDual::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanPhyDual")
+    .SetParent<UanPhy> ()
+    .AddConstructor<UanPhyDual> ()
+    .AddAttribute  ("CcaThresholdPhy1",
+                    "Aggregate energy of incoming signals to move to CCA Busy state dB of Phy1",
+                    DoubleValue (10),
+                    MakeDoubleAccessor (&UanPhyDual::GetCcaThresholdPhy1, &UanPhyDual::SetCcaThresholdPhy1),
+                    MakeDoubleChecker<double> ())
+    .AddAttribute ("CcaThresholdPhy2",
+                   "Aggregate energy of incoming signals to move to CCA Busy state dB of Phy2",
+                   DoubleValue (10),
+                   MakeDoubleAccessor (&UanPhyDual::GetCcaThresholdPhy2, &UanPhyDual::SetCcaThresholdPhy2),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPowerPhy1",
+                   "Transmission output power in dB of Phy1",
+                   DoubleValue (190),
+                   MakeDoubleAccessor (&UanPhyDual::GetTxPowerDbPhy1, &UanPhyDual::SetTxPowerDbPhy1),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPowerPhy2",
+                   "Transmission output power in dB of Phy2",
+                   DoubleValue (190),
+                   MakeDoubleAccessor (&UanPhyDual::GetTxPowerDbPhy2, &UanPhyDual::SetTxPowerDbPhy2),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxGainPhy1",
+                   "Gain added to incoming signal at receiver of Phy1",
+                   DoubleValue (0),
+                   MakeDoubleAccessor (&UanPhyDual::GetRxGainDbPhy1, &UanPhyDual::SetRxGainDbPhy1),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxGainPhy2",
+                   "Gain added to incoming signal at receiver of Phy2",
+                   DoubleValue (0),
+                   MakeDoubleAccessor (&UanPhyDual::GetRxGainDbPhy2, &UanPhyDual::SetRxGainDbPhy2),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("SupportedModesPhy1",
+                   "List of modes supported by Phy1",
+                   UanModesListValue (UanPhyGen::GetDefaultModes ()),
+                   MakeUanModesListAccessor (&UanPhyDual::GetModesPhy1, &UanPhyDual::SetModesPhy1),
+                   MakeUanModesListChecker () )
+    .AddAttribute ("SupportedModesPhy2",
+                   "List of modes supported by Phy2",
+                   UanModesListValue (UanPhyGen::GetDefaultModes ()),
+                   MakeUanModesListAccessor (&UanPhyDual::GetModesPhy2, &UanPhyDual::SetModesPhy2),
+                   MakeUanModesListChecker () )
+    .AddAttribute ("PerModelPhy1",
+                   "Functor to calculate PER based on SINR and TxMode for Phy1",
+                   PointerValue (CreateObject<UanPhyPerGenDefault> ()),
+                   MakePointerAccessor (&UanPhyDual::GetPerModelPhy1, &UanPhyDual::SetPerModelPhy1),
+                   MakePointerChecker<UanPhyPer> ())
+    .AddAttribute ("PerModelPhy2",
+                   "Functor to calculate PER based on SINR and TxMode for Phy2",
+                   PointerValue (CreateObject<UanPhyPerGenDefault> ()),
+                   MakePointerAccessor (&UanPhyDual::GetPerModelPhy2, &UanPhyDual::SetPerModelPhy2),
+                   MakePointerChecker<UanPhyPer> ())
+    .AddAttribute ("SinrModelPhy1",
+                   "Functor to calculate SINR based on pkt arrivals and modes for Phy1",
+                   PointerValue (CreateObject<UanPhyCalcSinrDual> ()),
+                   MakePointerAccessor (&UanPhyDual::GetSinrModelPhy1, &UanPhyDual::SetSinrModelPhy1),
+                   MakePointerChecker<UanPhyCalcSinr> ())
+    .AddAttribute ("SinrModelPhy2",
+                   "Functor to calculate SINR based on pkt arrivals and modes for Phy2",
+                   PointerValue (CreateObject<UanPhyCalcSinrDual> ()),
+                   MakePointerAccessor (&UanPhyDual::GetSinrModelPhy2, &UanPhyDual::SetSinrModelPhy2),
+                   MakePointerChecker<UanPhyCalcSinr> ())
+    .AddTraceSource ("RxOk",
+                     "A packet was received successfully",
+                     MakeTraceSourceAccessor (&UanPhyDual::m_rxOkLogger))
+    .AddTraceSource ("RxError",
+                     "A packet was received unsuccessfully",
+                     MakeTraceSourceAccessor (&UanPhyDual::m_rxErrLogger))
+    .AddTraceSource ("Tx",
+                     "Packet transmission beginning",
+                     MakeTraceSourceAccessor (&UanPhyDual::m_txLogger))
+
+  ;
+
+  return tid;
+}
+
+void
+UanPhyDual::SendPacket (Ptr<Packet> pkt, uint32_t modeNum)
+{
+  if (modeNum <= m_phy1->GetNModes () - 1)
+    {
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending packet on Phy1 with mode number " << modeNum);
+      m_txLogger (pkt, m_phy1->GetTxPowerDb (), m_phy1->GetMode (modeNum));
+      m_phy1->SendPacket (pkt, modeNum);
+
+    }
+  else
+    {
+      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending packet on Phy2 with mode number " << modeNum - m_phy1->GetNModes ());
+      m_txLogger (pkt, m_phy2->GetTxPowerDb (), m_phy2->GetMode (modeNum - m_phy1->GetNModes ()));
+      m_phy2->SendPacket (pkt, modeNum - m_phy1->GetNModes ());
+    }
+}
+void
+UanPhyDual::RegisterListener (UanPhyListener *listener)
+{
+  m_phy1->RegisterListener (listener);
+  m_phy2->RegisterListener (listener);
+}
+
+void
+UanPhyDual::StartRxPacket (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp)
+{
+  // Not called.  StartRxPacket in m_phy1 and m_phy2 are called directly from Transducer.
+}
+
+void
+UanPhyDual::SetReceiveOkCallback (RxOkCallback cb)
+{
+  m_phy1->SetReceiveOkCallback (cb);
+  m_phy2->SetReceiveOkCallback (cb);
+}
+
+void
+UanPhyDual::SetReceiveErrorCallback (RxErrCallback cb)
+{
+  m_phy1->SetReceiveErrorCallback (cb);
+  m_phy2->SetReceiveErrorCallback (cb);
+}
+
+void
+UanPhyDual::SetRxGainDb (double gain)
+{
+  m_phy1->SetRxGainDb (gain);
+  m_phy2->SetRxGainDb (gain);
+}
+void
+UanPhyDual::SetRxGainDbPhy1 (double gain)
+{
+  m_phy1->SetRxGainDb (gain);
+}
+
+void
+UanPhyDual::SetRxGainDbPhy2 (double gain)
+{
+  m_phy2->SetRxGainDb (gain);
+}
+
+void
+UanPhyDual::SetTxPowerDb (double txpwr)
+{
+  m_phy1->SetTxPowerDb (txpwr);
+  m_phy2->SetTxPowerDb (txpwr);
+}
+
+void
+UanPhyDual::SetTxPowerDbPhy1 (double txpwr)
+{
+  m_phy1->SetTxPowerDb (txpwr);
+}
+void
+UanPhyDual::SetTxPowerDbPhy2 (double txpwr)
+{
+  m_phy2->SetTxPowerDb (txpwr);
+}
+
+void
+UanPhyDual::SetRxThresholdDb (double thresh)
+{
+  NS_LOG_WARN ("SetRxThresholdDb is deprecated and has no effect.  Look at PER Functor attribute");
+  m_phy1->SetRxThresholdDb (thresh);
+  m_phy2->SetRxThresholdDb (thresh);
+}
+void
+UanPhyDual::SetCcaThresholdDb (double thresh)
+{
+  m_phy1->SetCcaThresholdDb (thresh);
+  m_phy2->SetCcaThresholdDb (thresh);
+}
+
+void
+UanPhyDual::SetCcaThresholdPhy1 (double thresh)
+{
+  m_phy1->SetCcaThresholdDb (thresh);
+}
+void
+UanPhyDual::SetCcaThresholdPhy2 (double thresh)
+{
+  m_phy2->SetCcaThresholdDb (thresh);
+}
+
+double
+UanPhyDual::GetRxGainDb (void)
+{
+  NS_LOG_WARN ("Warning: UanPhyDual::GetRxGainDb returns RxGain of Phy 1");
+  return m_phy1->GetRxGainDb ();
+}
+double
+UanPhyDual::GetRxGainDbPhy1 (void) const
+{
+  return m_phy1->GetRxGainDb ();
+}
+double
+UanPhyDual::GetRxGainDbPhy2 (void) const
+{
+  return m_phy2->GetRxGainDb ();
+}
+
+double
+UanPhyDual::GetTxPowerDb (void)
+{
+  NS_LOG_WARN ("Warning: Dual Phy only returns TxPowerDb of Phy 1");
+  return m_phy1->GetTxPowerDb ();
+}
+
+double
+UanPhyDual::GetTxPowerDbPhy1 (void) const
+{
+  return m_phy1->GetTxPowerDb ();
+}
+
+double
+UanPhyDual::GetTxPowerDbPhy2 (void) const
+{
+  return m_phy2->GetTxPowerDb ();
+}
+
+double
+UanPhyDual::GetRxThresholdDb (void)
+{
+  return m_phy1->GetRxThresholdDb ();
+}
+
+double
+UanPhyDual::GetCcaThresholdDb (void)
+{
+  NS_LOG_WARN ("Dual Phy only returns CCAThreshold of Phy 1");
+  return m_phy1->GetCcaThresholdDb ();
+}
+double
+UanPhyDual::GetCcaThresholdPhy1 (void) const
+{
+  return m_phy1->GetCcaThresholdDb ();
+}
+double
+UanPhyDual::GetCcaThresholdPhy2 (void) const
+{
+  return m_phy2->GetCcaThresholdDb ();
+}
+
+bool
+UanPhyDual::IsPhy1Idle (void)
+{
+  return m_phy1->IsStateIdle ();
+}
+bool
+UanPhyDual::IsPhy2Idle (void)
+{
+  return m_phy2->IsStateIdle ();
+}
+
+bool
+UanPhyDual::IsPhy1Rx (void)
+{
+  return m_phy1->IsStateRx ();
+}
+
+bool
+UanPhyDual::IsPhy2Rx (void)
+{
+  return m_phy2->IsStateRx ();
+}
+
+bool
+UanPhyDual::IsPhy1Tx (void)
+{
+  return m_phy1->IsStateTx ();
+}
+
+Ptr<Packet>
+UanPhyDual::GetPhy1PacketRx (void) const
+{
+  return m_phy1->GetPacketRx ();
+}
+
+Ptr<Packet>
+UanPhyDual::GetPhy2PacketRx (void) const
+{
+  return m_phy2->GetPacketRx ();
+}
+
+bool
+UanPhyDual::IsPhy2Tx (void)
+{
+  return m_phy2->IsStateTx ();
+}
+
+bool
+UanPhyDual::IsStateIdle (void)
+{
+  return m_phy1->IsStateIdle () && m_phy2->IsStateIdle ();
+}
+bool
+UanPhyDual::IsStateBusy (void)
+{
+  return !IsStateIdle ();
+}
+bool
+UanPhyDual::IsStateRx (void)
+{
+  return m_phy1->IsStateRx () || m_phy2->IsStateRx ();
+}
+bool
+UanPhyDual::IsStateTx (void)
+{
+  return m_phy1->IsStateTx () || m_phy2->IsStateTx ();
+}
+bool
+UanPhyDual::IsStateCcaBusy (void)
+{
+  return m_phy1->IsStateCcaBusy () || m_phy2->IsStateCcaBusy ();
+}
+Ptr<UanChannel>
+UanPhyDual::GetChannel (void) const
+{
+  return m_phy1->GetChannel ();
+}
+Ptr<UanNetDevice>
+UanPhyDual::GetDevice (void)
+{
+  return m_phy1->GetDevice ();
+}
+void
+UanPhyDual::SetChannel (Ptr<UanChannel> channel)
+{
+  m_phy1->SetChannel (channel);
+  m_phy2->SetChannel (channel);
+}
+void
+UanPhyDual::SetDevice (Ptr<UanNetDevice> device)
+{
+  m_phy1->SetDevice (device);
+  m_phy2->SetDevice (device);
+}
+void
+UanPhyDual::SetMac (Ptr<UanMac> mac)
+{
+  m_phy1->SetMac (mac);
+  m_phy2->SetMac (mac);
+}
+void
+UanPhyDual::NotifyTransStartTx (Ptr<Packet> packet, double txPowerDb, UanTxMode txMode)
+{
+
+}
+void
+UanPhyDual::NotifyIntChange (void)
+{
+  m_phy1->NotifyIntChange ();
+  m_phy2->NotifyIntChange ();
+
+}
+void
+UanPhyDual::SetTransducer (Ptr<UanTransducer> trans)
+{
+  m_phy1->SetTransducer (trans);
+  m_phy2->SetTransducer (trans);
+}
+Ptr<UanTransducer>
+UanPhyDual::GetTransducer (void)
+{
+  NS_LOG_WARN ("DualPhy Returning transducer of Phy1");
+  return m_phy1->GetTransducer ();
+}
+uint32_t
+UanPhyDual::GetNModes (void)
+{
+  return m_phy1->GetNModes () + m_phy2->GetNModes ();
+}
+UanTxMode
+UanPhyDual::GetMode (uint32_t n)
+{
+  if (n < m_phy1->GetNModes ())
+    {
+      return m_phy1->GetMode (n);
+    }
+  else
+    {
+      return m_phy2->GetMode (n - m_phy1->GetNModes ());
+    }
+}
+
+UanModesList
+UanPhyDual::GetModesPhy1 (void) const
+{
+
+  UanModesListValue modeValue;
+  m_phy1->GetAttribute ("SupportedModes", modeValue);
+  return modeValue.Get ();
+}
+
+UanModesList
+UanPhyDual::GetModesPhy2 (void) const
+{
+  UanModesListValue modeValue;
+  m_phy2->GetAttribute ("SupportedModes", modeValue);
+  return modeValue.Get ();
+}
+
+void
+UanPhyDual::SetModesPhy1 (UanModesList modes)
+{
+  m_phy1->SetAttribute ("SupportedModes", UanModesListValue (modes));
+}
+
+void
+UanPhyDual::SetModesPhy2 (UanModesList modes)
+{
+  m_phy2->SetAttribute ("SupportedModes", UanModesListValue (modes));
+}
+
+Ptr<UanPhyPer>
+UanPhyDual::GetPerModelPhy1 (void) const
+{
+  PointerValue perValue;
+  m_phy1->GetAttribute ("PerModel", perValue);
+  return perValue;
+}
+
+Ptr<UanPhyPer>
+UanPhyDual::GetPerModelPhy2 (void) const
+{
+  PointerValue perValue;
+  m_phy2->GetAttribute ("PerModel", perValue);
+  return perValue;
+}
+
+void
+UanPhyDual::SetPerModelPhy1 (Ptr<UanPhyPer> per)
+{
+  m_phy1->SetAttribute ("PerModel", PointerValue (per));
+}
+
+void
+UanPhyDual::SetPerModelPhy2 (Ptr<UanPhyPer> per)
+{
+  m_phy2->SetAttribute ("PerModel", PointerValue (per));
+}
+
+Ptr<UanPhyCalcSinr>
+UanPhyDual::GetSinrModelPhy1 (void) const
+{
+  PointerValue sinrValue;
+  m_phy1->GetAttribute ("SinrModel", sinrValue);
+  return sinrValue;
+}
+
+Ptr<UanPhyCalcSinr>
+UanPhyDual::GetSinrModelPhy2 (void) const
+{
+  PointerValue sinrValue;
+  m_phy2->GetAttribute ("SinrModel", sinrValue);
+  return sinrValue;
+}
+
+void
+UanPhyDual::SetSinrModelPhy1 (Ptr<UanPhyCalcSinr> sinr)
+{
+  m_phy1->SetAttribute ("SinrModel", PointerValue (sinr));
+}
+
+void
+UanPhyDual::SetSinrModelPhy2 (Ptr<UanPhyCalcSinr> sinr)
+{
+  m_phy2->SetAttribute ("SinrModel", PointerValue (sinr));
+}
+
+void
+UanPhyDual::RxOkFromSubPhy (Ptr<Packet> pkt, double sinr, UanTxMode mode)
+{
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Received packet");
+  m_recOkCb (pkt, sinr, mode);
+  m_rxOkLogger (pkt, sinr, mode);
+}
+
+void
+UanPhyDual::RxErrFromSubPhy (Ptr<Packet> pkt, double sinr)
+{
+  m_recErrCb (pkt, sinr);
+  m_rxErrLogger (pkt, sinr, m_phy1->GetMode (0));
+}
+
+Ptr<Packet>
+UanPhyDual::GetPacketRx (void) const
+{
+  NS_FATAL_ERROR ("GetPacketRx not valid for UanPhyDual.  Must specify GetPhy1PacketRx or GetPhy2PacketRx");
+  return Create<Packet> ();
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-phy-dual.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,280 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANPHYDUAL_H
+#define UANPHYDUAL_H
+
+#include "uan-phy.h"
+
+
+
+namespace ns3 {
+namespace uan {
+
+class UanTxMode;
+class UanModesList;
+
+
+/**
+ * \class UanPhyCalcSinrDual
+ * \brief Default SINR model for UanPhyDual
+ *
+ * Considers interfering packet power as additional ambient noise only
+ * if there is overlap in frequency band as found from supplied UanTxMode.
+ * If there is no overlap, then the packets are considered not to interfere.
+ */
+class UanPhyCalcSinrDual : public UanPhyCalcSinr
+{
+public:
+  UanPhyCalcSinrDual ();
+  virtual ~UanPhyCalcSinrDual ();
+  static TypeId GetTypeId (void);
+  virtual double CalcSinrDb (Ptr<Packet> pkt,
+                             Time arrTime,
+                             double rxPowerDb,
+                             double ambNoiseDb,
+                             UanTxMode mode,
+                             UanPdp pdp,
+                             const UanTransducer::ArrivalList &arrivalList
+                             ) const;
+};
+
+/**
+ * \class UanPhyDual
+ *
+ * A class that wraps two generic UAN Phy layers (UanPhyGen) into a single PHY.
+ * This is used to simulate two receivers (and transmitters) that use
+ * the same front end hardware.  When attached to a UanTransducerHd,
+ * this results in a net device able to transmit on one or two channels
+ * simultaneously or receive on one or two channels simultaneously but
+ * that cannot transmit and receive simultaneously.
+ *
+ * Many of the standard PHY functions here become ambiguous.  In most cases
+ * information for "Phy1" are returned.
+ */
+class UanPhyDual : public UanPhy
+{
+public:
+  UanPhyDual ();
+  virtual ~UanPhyDual ();
+
+  static TypeId GetTypeId ();
+
+  virtual void SendPacket (Ptr<Packet> pkt, uint32_t modeNum);
+
+  /**
+   * \brief Register a class to receive phy state change notifications
+   * \param listener Class derived from UanPhyListener to receive notifications
+   *
+   * Note that, from UanPhyDual, you may receive duplicate
+   * messages as underneath there are two generic phys here.
+   * Each will notify of state changes independently.
+   */
+  virtual void RegisterListener (UanPhyListener *listener);
+  virtual void StartRxPacket (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp);
+  virtual void SetReceiveOkCallback (RxOkCallback cb);
+  virtual void SetReceiveErrorCallback (RxErrCallback cb);
+  virtual void SetRxGainDb (double gain);
+  virtual void SetTxPowerDb (double txpwr);
+  virtual void SetRxThresholdDb (double thresh);
+  virtual void SetCcaThresholdDb (double thresh);
+  virtual double GetRxGainDb (void);
+  virtual double GetTxPowerDb (void);
+  virtual double GetRxThresholdDb (void);
+  virtual double GetCcaThresholdDb (void);
+  virtual bool IsStateIdle (void);
+  virtual bool IsStateBusy (void);
+  virtual bool IsStateRx (void);
+  virtual bool IsStateTx (void);
+  virtual bool IsStateCcaBusy (void);
+  virtual Ptr<UanChannel> GetChannel (void) const;
+  virtual Ptr<UanNetDevice> GetDevice (void);
+  virtual void SetChannel (Ptr<UanChannel> channel);
+  virtual void SetDevice (Ptr<UanNetDevice> device);
+  virtual void SetMac (Ptr<UanMac> mac);
+  virtual void NotifyTransStartTx (Ptr<Packet> packet, double txPowerDb, UanTxMode txMode);
+  virtual void NotifyIntChange (void);
+  virtual void SetTransducer (Ptr<UanTransducer> trans);
+  virtual Ptr<UanTransducer> GetTransducer (void);
+  virtual uint32_t GetNModes (void);
+  virtual UanTxMode GetMode (uint32_t n);
+  virtual void Clear (void);
+
+  /**
+   * /returns True if Phy1 is Idle
+   */
+  bool IsPhy1Idle (void);
+  /**
+   * /returns True if Phy2 is Idle
+   */
+  bool IsPhy2Idle (void);
+  /**
+   * /returns True if Phy1 is currently in RX mode
+   */
+  bool IsPhy1Rx (void);
+  /**
+   * /returns True if Phy2 is currently in RX mode
+   */
+  bool IsPhy2Rx (void);
+  /**
+   * /returns True if Phy1 is in TX mode
+   */
+  bool IsPhy1Tx (void);
+  /**
+   * /returns True if Phy2 is in TX mode
+   */
+  bool IsPhy2Tx (void);
+
+  // Attribute getters and setters
+  /**
+   * \returns Clear channel assessment threshold of Phy1
+   */
+  double GetCcaThresholdPhy1 (void) const;
+  /**
+   * \returns Clear channel assessment threshold of Phy2
+   */
+  double GetCcaThresholdPhy2 (void) const;
+  /**
+   * \param thresh Signal power threshold in dB to set Phy1 to
+   */
+  void SetCcaThresholdPhy1 (double thresh);
+  /**
+   * \param thresh Signal power threshold in dB to set Phy2 to
+   */
+  void SetCcaThresholdPhy2 (double thresh);
+
+  /**
+   * \returns Current TX power setting of Phy 1 in dB
+   */
+  double GetTxPowerDbPhy1 (void) const;
+  /**
+   * \returns Current TX power setting of Phy 2 in dB
+   */
+  double GetTxPowerDbPhy2 (void) const;
+  /**
+   * \returns TX power setting of Phy1 in dB
+   */
+  void SetTxPowerDbPhy1 (double);
+  /**
+   * \returns TX power setting of Phy2 in dB
+   */
+  void SetTxPowerDbPhy2 (double);
+
+  /**
+   * \returns RX gain of Phy1 in dB
+   */
+  double GetRxGainDbPhy1 (void) const;
+  /**
+   * \returns RX gain of Phy2 in dB
+   */
+  double GetRxGainDbPhy2 (void) const;
+  /**
+   * \param gain value in dB to apply to RX gain of Phy1
+   */
+  void SetRxGainDbPhy1 (double gain);
+  /**
+   * \param gain value in dB to apply to RX gain of Phy2
+   */
+  void SetRxGainDbPhy2 (double gain);
+
+  /**
+   * \returns List of available modes on Phy1
+   */
+  UanModesList GetModesPhy1 (void) const;
+  /**
+   * \returns List of available modes on Phy2
+   */
+  UanModesList GetModesPhy2 (void) const;
+  /**
+   * \param modes List of modes to use on Phy1 (index corresponds to mode #)
+   */
+  void SetModesPhy1 (UanModesList modes);
+  /**
+   * \param modes List of modes to use on Phy2 (index corresponds to mode #)
+   */
+  void SetModesPhy2 (UanModesList modes);
+
+  /**
+   * \returns Ptr to PER model for Phy1
+   */
+  Ptr<UanPhyPer> GetPerModelPhy1 (void) const;
+  /**
+   * \returns Ptr to PER model for Phy2
+   */
+  Ptr<UanPhyPer> GetPerModelPhy2 (void) const;
+  /**
+   * \param per Ptr to PER model to use on Phy1
+   */
+  void SetPerModelPhy1 (Ptr<UanPhyPer> per);
+  /**
+   * \param per Ptr to PER model to use on Phy2
+   */
+  void SetPerModelPhy2 (Ptr<UanPhyPer> per);
+
+  /**
+   * \returns Ptr to SINR model for Phy1
+   */
+  Ptr<UanPhyCalcSinr> GetSinrModelPhy1 (void) const;
+  /**
+   * \returns Ptr to SINR model for Phy2
+   */
+  Ptr<UanPhyCalcSinr> GetSinrModelPhy2 (void) const;
+  /**
+   * \param calcSinr Ptr to SINR model to use on Phy1
+   */
+  void SetSinrModelPhy1 (Ptr<UanPhyCalcSinr> calcSinr);
+  /**
+   * \param calcSinr Ptr to SINR model to use on Phy2
+   */
+  void SetSinrModelPhy2 (Ptr<UanPhyCalcSinr> calcSinr);
+
+  /**
+   * \returns Packet currently being received on Phy1 (Null Ptr if none)
+   */
+  Ptr<Packet> GetPhy1PacketRx (void) const;
+  /**
+   * \returns Packet currently being received on Phy2 (Null Ptr if none)
+   */
+  Ptr<Packet> GetPhy2PacketRx (void) const;
+  /**
+   * \returns Packet currenty being received on Phy1 (Null Ptr if none)
+   */
+  Ptr<Packet> GetPacketRx (void) const;
+
+private:
+  Ptr<UanPhy> m_phy1;
+  Ptr<UanPhy> m_phy2;
+  TracedCallback<Ptr<const Packet>, double, UanTxMode > m_rxOkLogger;
+  TracedCallback<Ptr<const Packet>, double, UanTxMode > m_rxErrLogger;
+  TracedCallback<Ptr<const Packet>, double, UanTxMode > m_txLogger;
+  RxOkCallback m_recOkCb;
+  RxErrCallback m_recErrCb;
+
+
+  void RxOkFromSubPhy (Ptr<Packet> pkt, double sinr, UanTxMode mode);
+  void RxErrFromSubPhy (Ptr<Packet> pkt, double sinr);
+protected:
+  virtual void DoDispose ();
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANPHYDUAL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-phy-gen.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,901 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-phy-gen.h"
+#include "uan-transducer.h"
+#include "uan-channel.h"
+#include "uan-net-device.h"
+#include "ns3/simulator.h"
+#include "ns3/traced-callback.h"
+#include "ns3/ptr.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/double.h"
+#include "ns3/log.h"
+#include "uan-tx-mode.h"
+#include "ns3/node.h"
+#include "ns3/uinteger.h"
+#include "ns3/random-variable.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("UanPhyGen");
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanPhyGen);
+NS_OBJECT_ENSURE_REGISTERED (UanPhyPerGenDefault);
+NS_OBJECT_ENSURE_REGISTERED (UanPhyCalcSinrDefault);
+NS_OBJECT_ENSURE_REGISTERED (UanPhyCalcSinrFhFsk);
+NS_OBJECT_ENSURE_REGISTERED (UanPhyPerUmodem);
+
+
+/*************** UanPhyCalcSinrDefault definition *****************/
+UanPhyCalcSinrDefault::UanPhyCalcSinrDefault ()
+{
+
+}
+UanPhyCalcSinrDefault::~UanPhyCalcSinrDefault ()
+{
+
+}
+
+TypeId
+UanPhyCalcSinrDefault::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanPhyCalcSinrDefault")
+    .SetParent<Object> ()
+    .AddConstructor<UanPhyCalcSinrDefault> ()
+  ;
+  return tid;
+}
+
+double
+UanPhyCalcSinrDefault::CalcSinrDb (Ptr<Packet> pkt,
+                                   Time arrTime,
+                                   double rxPowerDb,
+                                   double ambNoiseDb,
+                                   UanTxMode mode,
+                                   UanPdp pdp,
+                                   const UanTransducer::ArrivalList &arrivalList) const
+{
+  if (mode.GetModType () == UanTxMode::OTHER)
+    {
+      NS_LOG_WARN ("Calculating SINR for unsupported modulation type");
+    }
+
+  double intKp = -DbToKp (rxPowerDb); // This packet is in the arrivalList
+  UanTransducer::ArrivalList::const_iterator it = arrivalList.begin ();
+  for (; it != arrivalList.end (); it++)
+    {
+      intKp += DbToKp (it->GetRxPowerDb ());
+    }
+
+  double totalIntDb = KpToDb (intKp + DbToKp (ambNoiseDb));
+
+  NS_LOG_DEBUG ("Calculating SINR:  RxPower = " << rxPowerDb << " dB.  Number of interferers = " << arrivalList.size () << "  Interference + noise power = " << totalIntDb << " dB.  SINR = " << rxPowerDb - totalIntDb << " dB.");
+  return rxPowerDb - totalIntDb;
+}
+
+/*************** UanPhyCalcSinrFhFsk definition *****************/
+UanPhyCalcSinrFhFsk::UanPhyCalcSinrFhFsk ()
+{
+
+}
+UanPhyCalcSinrFhFsk::~UanPhyCalcSinrFhFsk ()
+{
+
+}
+
+TypeId
+UanPhyCalcSinrFhFsk::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanPhyCalcSinrFhFsk")
+    .SetParent<Object> ()
+    .AddConstructor<UanPhyCalcSinrFhFsk> ()
+    .AddAttribute ("NumberOfHops",
+                   "Number of frequencies in hopping pattern",
+                   UintegerValue (13),
+                   MakeUintegerAccessor (&UanPhyCalcSinrFhFsk::m_hops),
+                   MakeUintegerChecker<uint32_t> ())
+  ;
+  return tid;
+}
+double
+UanPhyCalcSinrFhFsk::CalcSinrDb (Ptr<Packet> pkt,
+                                 Time arrTime,
+                                 double rxPowerDb,
+                                 double ambNoiseDb,
+                                 UanTxMode mode,
+                                 UanPdp pdp,
+                                 const UanTransducer::ArrivalList &arrivalList) const
+{
+  if (mode.GetModType () != UanTxMode::FSK)
+    {
+      NS_LOG_WARN ("Calculating SINR for unsupported mode type");
+    }
+
+
+
+  double ts = 1.0 / mode.GetPhyRateSps ();
+  double clearingTime = (m_hops - 1.0) * ts;
+  double csp = pdp.SumTapsFromMaxNc (Seconds (0), Seconds (ts));
+
+  UanPdp::Iterator tmpIt = pdp.GetBegin ();
+
+  // Get maximum arrival offset
+  double maxAmp = -1;
+  double maxTapDelay = 0.0;
+  UanPdp::Iterator pit = pdp.GetBegin ();
+  for (; pit != pdp.GetEnd (); pit++)
+    {
+      if (abs (pit->GetAmp ()) > maxAmp)
+        {
+          maxAmp = abs (pit->GetAmp ());
+          maxTapDelay = pit->GetDelay ().GetSeconds ();
+        }
+    }
+
+
+  double effRxPowerDb = rxPowerDb + KpToDb (csp);
+
+  double isiUpa = rxPowerDb * pdp.SumTapsFromMaxNc (Seconds (ts + clearingTime), Seconds (ts));
+  UanTransducer::ArrivalList::const_iterator it = arrivalList.begin ();
+  double intKp = -DbToKp (effRxPowerDb);
+  for (; it != arrivalList.end (); it++)
+    {
+      UanPdp intPdp = it->GetPdp ();
+      double tDelta = std::abs (arrTime.GetSeconds () + maxTapDelay - it->GetArrivalTime ().GetSeconds ());
+      // We want tDelta in terms of a single symbol (i.e. if tDelta = 7.3 symbol+clearing
+      // times, the offset in terms of the arriving symbol power is
+      // 0.3 symbol+clearing times.
+
+      int32_t syms = (uint32_t)( (double) tDelta / (ts + clearingTime));
+      tDelta = tDelta - syms * (ts + clearingTime);
+
+      // Align to pktRx
+      if (arrTime + Seconds (maxTapDelay)  > it->GetArrivalTime ())
+        {
+          tDelta = ts + clearingTime - tDelta;
+        }
+
+      double intPower = 0.0;
+      if (tDelta < ts)
+        {
+          intPower += intPdp.SumTapsNc (Seconds (0), Seconds (ts - tDelta));
+          intPower += intPdp.SumTapsNc (Seconds (ts - tDelta + clearingTime),
+                                        Seconds (2 * ts - tDelta + clearingTime));
+        }
+      else
+        {
+          Time start = Seconds (ts + clearingTime - tDelta);
+          Time end = start + Seconds (ts);
+          intPower += intPdp.SumTapsNc (start, end);
+
+          start = start + Seconds (ts + clearingTime);
+          end = start + Seconds (ts);
+          intPower += intPdp.SumTapsNc (start, end);
+        }
+      intKp += DbToKp (it->GetRxPowerDb ()) * intPower;
+    }
+
+  double totalIntDb = KpToDb (isiUpa + intKp + DbToKp (ambNoiseDb));
+
+  NS_LOG_DEBUG ("Calculating SINR:  RxPower = " << rxPowerDb << " dB.  Effective Rx power " << effRxPowerDb << " dB.  Number of interferers = " << arrivalList.size () << "  Interference + noise power = " << totalIntDb << " dB.  SINR = " << effRxPowerDb - totalIntDb << " dB.");
+  return effRxPowerDb - totalIntDb;
+}
+
+/*************** UanPhyPerGenDefault definition *****************/
+UanPhyPerGenDefault::UanPhyPerGenDefault ()
+{
+
+}
+
+UanPhyPerGenDefault::~UanPhyPerGenDefault ()
+{
+
+}
+TypeId
+UanPhyPerGenDefault::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanPhyPerGenDefault")
+    .SetParent<Object> ()
+    .AddConstructor<UanPhyPerGenDefault> ()
+    .AddAttribute ("Threshold", "SINR cutoff for good packet reception",
+                   DoubleValue (8),
+                   MakeDoubleAccessor (&UanPhyPerGenDefault::m_thresh),
+                   MakeDoubleChecker<double> ());
+  return tid;
+}
+
+
+// Default PER calculation simply compares SINR to a threshold which is configurable
+// via an attribute.
+double
+UanPhyPerGenDefault::CalcPer (Ptr<Packet> pkt, double sinrDb, UanTxMode mode)
+{
+  if (sinrDb >= m_thresh)
+    {
+      return 0;
+    }
+  else
+    {
+      return 1;
+    }
+}
+
+/*************** UanPhyPerUmodem definition *****************/
+UanPhyPerUmodem::UanPhyPerUmodem ()
+{
+
+}
+UanPhyPerUmodem::~UanPhyPerUmodem ()
+{
+
+}
+
+TypeId UanPhyPerUmodem::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanPhyPerUmodem")
+    .SetParent<Object> ()
+    .AddConstructor<UanPhyPerUmodem> ()
+  ;
+  return tid;
+}
+
+double
+UanPhyPerUmodem::NChooseK (uint32_t n, uint32_t k)
+{
+  double result;
+
+  result = 1.0;
+
+  for (uint32_t i = std::max (k,n - k) + 1; i <= n; ++i)
+    {
+      result *= i;
+    }
+
+  for (uint32_t i = 2; i <= std::min (k,n - k); ++i)
+    {
+      result /= i;
+    }
+
+  return result;
+}
+
+double
+UanPhyPerUmodem::CalcPer (Ptr<Packet> pkt, double sinr, UanTxMode mode)
+{
+  uint32_t d[] =
+  { 12, 14, 16, 18, 20, 22, 24, 26, 28 };
+  double Bd[] =
+  {
+    33, 281, 2179, 15035LLU, 105166LLU, 692330LLU, 4580007LLU, 29692894LLU,
+    190453145LLU
+  };
+
+  // double Rc = 1.0 / 2.0;
+  double ebno = std::pow (10.0, sinr / 10.0);
+  double perror = 1.0 / (2.0 + ebno);
+  double P[9];
+
+  if (sinr >= 10)
+    {
+      return 0;
+    }
+  if (sinr <= 6)
+    {
+      return 1;
+    }
+
+  for (uint32_t r = 0; r < 9; r++)
+    {
+      double sumd = 0;
+      for (uint32_t k = 0; k < d[r]; k++)
+        {
+          sumd = sumd + NChooseK (d[r] - 1 + k, k) * std::pow (1 - perror, (double) k);
+        }
+      P[r] = std::pow (perror, (double) d[r]) * sumd;
+
+    }
+
+  double Pb = 0;
+  for (uint32_t r = 0; r < 8; r++)
+    {
+      Pb = Pb + Bd[r] * P[r];
+    }
+
+  // cout << "Pb = " << Pb << endl;
+  uint32_t bits = pkt->GetSize () * 8;
+
+  double Ppacket = 1;
+  double temp = NChooseK (bits, 0);
+  temp *= std::pow ( (1 - Pb), (double) bits);
+  Ppacket -= temp;
+  temp = NChooseK (288, 1) * Pb * std::pow ( (1 - Pb), bits - 1.0);
+  Ppacket -= temp;
+
+  if (Ppacket > 1)
+    {
+      return 1;
+    }
+  else
+    {
+      return Ppacket;
+    }
+}
+
+/*************** UanPhyGen definition *****************/
+UanPhyGen::UanPhyGen ()
+  : UanPhy (),
+    m_state (IDLE),
+    m_channel (0),
+    m_transducer (0),
+    m_device (0),
+    m_mac (0),
+    m_rxGainDb (0),
+    m_txPwrDb (0),
+    m_rxThreshDb (0),
+    m_ccaThreshDb (0),
+    m_pktRx (0),
+    m_cleared (false)
+{
+
+}
+
+UanPhyGen::~UanPhyGen ()
+{
+
+}
+
+void
+UanPhyGen::Clear ()
+{
+  if (m_cleared)
+    {
+      return;
+    }
+  m_cleared = true;
+  m_listeners.clear ();
+  if (m_channel)
+    {
+      m_channel->Clear ();
+      m_channel = 0;
+    }
+  if (m_transducer)
+    {
+      m_transducer->Clear ();
+      m_transducer = 0;
+    }
+  if (m_device)
+    {
+      m_device->Clear ();
+      m_device = 0;
+    }
+  if (m_mac)
+    {
+      m_mac->Clear ();
+      m_mac = 0;
+    }
+  if (m_per)
+    {
+      m_per->Clear ();
+      m_per = 0;
+    }
+  if (m_sinr)
+    {
+      m_sinr->Clear ();
+      m_sinr = 0;
+    }
+  m_pktRx = 0;
+}
+
+void
+UanPhyGen::DoDispose ()
+{
+  Clear ();
+  UanPhy::DoDispose ();
+}
+
+UanModesList
+UanPhyGen::GetDefaultModes (void)
+{
+  UanModesList l;
+  l.AppendMode (UanTxModeFactory::CreateMode (UanTxMode::FSK,80,80,22000,4000,13,"FSK"));
+  l.AppendMode (UanTxModeFactory::CreateMode (UanTxMode::PSK,200, 200, 22000, 4000, 4, "QPSK"));
+  return l;
+}
+TypeId
+UanPhyGen::GetTypeId (void)
+{
+
+  static TypeId tid = TypeId ("ns3::UanPhyGen")
+    .SetParent<Object> ()
+    .AddConstructor<UanPhyGen> ()
+    .AddAttribute ("CcaThreshold",
+                   "Aggregate energy of incoming signals to move to CCA Busy state dB",
+                   DoubleValue (10),
+                   MakeDoubleAccessor (&UanPhyGen::m_ccaThreshDb),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxThreshold",
+                   "Required SNR for signal acquisition in dB",
+                   DoubleValue (10),
+                   MakeDoubleAccessor (&UanPhyGen::m_rxThreshDb),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPower",
+                   "Transmission output power in dB",
+                   DoubleValue (190),
+                   MakeDoubleAccessor (&UanPhyGen::m_txPwrDb),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxGain",
+                   "Gain added to incoming signal at receiver",
+                   DoubleValue (0),
+                   MakeDoubleAccessor (&UanPhyGen::m_rxGainDb),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("SupportedModes",
+                   "List of modes supported by this PHY",
+                   UanModesListValue (UanPhyGen::GetDefaultModes ()),
+                   MakeUanModesListAccessor (&UanPhyGen::m_modes),
+                   MakeUanModesListChecker () )
+    .AddAttribute ("PerModel",
+                   "Functor to calculate PER based on SINR and TxMode",
+                   PointerValue (CreateObject<UanPhyPerGenDefault> ()),
+                   MakePointerAccessor (&UanPhyGen::m_per),
+                   MakePointerChecker<UanPhyPer> ())
+    .AddAttribute ("SinrModel",
+                   "Functor to calculate SINR based on pkt arrivals and modes",
+                   PointerValue (CreateObject<UanPhyCalcSinrDefault> ()),
+                   MakePointerAccessor (&UanPhyGen::m_sinr),
+                   MakePointerChecker<UanPhyCalcSinr> ())
+    .AddTraceSource ("RxOk",
+                     "A packet was received successfully",
+                     MakeTraceSourceAccessor (&UanPhyGen::m_rxOkLogger))
+    .AddTraceSource ("RxError",
+                     "A packet was received unsuccessfully",
+                     MakeTraceSourceAccessor (&UanPhyGen::m_rxErrLogger))
+    .AddTraceSource ("Tx",
+                     "Packet transmission beginning",
+                     MakeTraceSourceAccessor (&UanPhyGen::m_txLogger))
+  ;
+  return tid;
+
+}
+
+void
+UanPhyGen::SendPacket (Ptr<Packet> pkt, uint32_t modeNum)
+{
+  NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << ": Transmitting packet");
+  if (m_state == TX)
+    {
+      NS_LOG_DEBUG ("PHY requested to TX while already Transmitting.  Dropping packet.");
+      return;
+    }
+
+  UanTxMode txMode = GetMode (modeNum);
+
+  if (m_pktRx != 0)
+    {
+      m_minRxSinrDb = -1e30;
+      m_pktRx = 0;
+    }
+
+  m_transducer->Transmit (Ptr<UanPhy> (this), pkt, m_txPwrDb, txMode);
+  m_state = TX;
+  double txdelay = pkt->GetSize () * 8.0 / txMode.GetDataRateBps ();
+  Simulator::Schedule (Seconds (txdelay), &UanPhyGen::TxEndEvent, this);
+  NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << " notifying listeners");
+  NotifyListenersTxStart (Seconds (txdelay));
+  m_txLogger (pkt, m_txPwrDb, txMode);
+}
+
+void
+UanPhyGen::TxEndEvent ()
+{
+  NS_ASSERT (m_state == TX);
+  if (GetInterferenceDb ( (Ptr<Packet>) 0) > m_ccaThreshDb)
+    {
+      m_state = CCABUSY;
+      NotifyListenersCcaStart ();
+    }
+  else
+    {
+      m_state = IDLE;
+    }
+}
+
+void
+UanPhyGen::RegisterListener (UanPhyListener *listener)
+{
+  m_listeners.push_back (listener);
+}
+
+
+void
+UanPhyGen::StartRxPacket (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp)
+{
+  switch (m_state)
+    {
+    case TX:
+      NS_ASSERT (false);
+      break;
+    case RX:
+      {
+        NS_ASSERT (m_pktRx);
+        double newSinrDb = CalculateSinrDb (m_pktRx, m_pktRxArrTime, m_rxRecvPwrDb, m_pktRxMode, m_pktRxPdp);
+        m_minRxSinrDb  =  (newSinrDb < m_minRxSinrDb) ? newSinrDb : m_minRxSinrDb;
+        NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << ": Starting RX in RX mode.  SINR of pktRx = " << m_minRxSinrDb);
+      }
+      break;
+
+    case CCABUSY:
+    case IDLE:
+      {
+        NS_ASSERT (!m_pktRx);
+        bool hasmode = false;
+        for (uint32_t i = 0; i < GetNModes (); i++)
+          {
+            if (txMode.GetUid () == GetMode (i).GetUid ())
+              {
+                hasmode = true;
+                break;
+              }
+          }
+        if (!hasmode)
+          {
+            break;
+          }
+
+
+        double newsinr = CalculateSinrDb (pkt, Simulator::Now (), rxPowerDb, txMode, pdp);
+        NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << ": Starting RX in IDLE mode.  SINR = " << newsinr);
+        if (newsinr > m_rxThreshDb)
+          {
+            m_state = RX;
+            m_rxRecvPwrDb = rxPowerDb;
+            m_minRxSinrDb = newsinr;
+            m_pktRx = pkt;
+            m_pktRxArrTime = Simulator::Now ();
+            m_pktRxMode = txMode;
+            m_pktRxPdp = pdp;
+            double txdelay = pkt->GetSize () * 8.0 / txMode.GetDataRateBps ();
+            Simulator::Schedule (Seconds (txdelay), &UanPhyGen::RxEndEvent, this, pkt, rxPowerDb, txMode);
+            NotifyListenersRxStart ();
+          }
+
+      }
+      break;
+    }
+
+  if (m_state == IDLE && GetInterferenceDb ( (Ptr<Packet>) 0) > m_ccaThreshDb)
+    {
+      m_state = CCABUSY;
+      NotifyListenersCcaStart ();
+    }
+
+}
+
+void
+UanPhyGen::RxEndEvent (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode)
+{
+  if (pkt != m_pktRx)
+    {
+      return;
+    }
+
+  if (GetInterferenceDb ( (Ptr<Packet>) 0) > m_ccaThreshDb)
+    {
+      m_state = CCABUSY;
+      NotifyListenersCcaStart ();
+    }
+  else
+    {
+      m_state = IDLE;
+    }
+
+  UniformVariable pg;
+
+  if (pg.GetValue (0, 1) > m_per->CalcPer (m_pktRx, m_minRxSinrDb, txMode))
+    {
+      m_rxOkLogger (pkt, m_minRxSinrDb, txMode);
+      NotifyListenersRxGood ();
+      if (!m_recOkCb.IsNull ())
+        {
+          m_recOkCb (pkt, m_minRxSinrDb, txMode);
+        }
+
+    }
+  else
+    {
+      m_rxErrLogger (pkt, m_minRxSinrDb, txMode);
+      NotifyListenersRxBad ();
+      if (!m_recErrCb.IsNull ())
+        {
+          m_recErrCb (pkt, m_minRxSinrDb);
+        }
+    }
+
+  m_pktRx = 0;
+}
+
+void
+UanPhyGen::SetReceiveOkCallback (RxOkCallback cb)
+{
+  m_recOkCb = cb;
+}
+
+void
+UanPhyGen::SetReceiveErrorCallback (RxErrCallback cb)
+{
+  m_recErrCb = cb;
+}
+
+
+bool
+UanPhyGen::IsStateIdle (void)
+{
+  return m_state == IDLE;
+}
+bool
+UanPhyGen::IsStateBusy (void)
+{
+  return m_state != IDLE;
+}
+bool
+UanPhyGen::IsStateRx (void)
+{
+  return m_state == RX;
+}
+bool
+UanPhyGen::IsStateTx (void)
+{
+  return m_state == TX;
+}
+
+bool
+UanPhyGen::IsStateCcaBusy (void)
+{
+  return m_state == CCABUSY;
+}
+
+
+void
+UanPhyGen::SetRxGainDb (double gain)
+{
+  m_rxGainDb = gain;
+
+}
+void
+UanPhyGen::SetTxPowerDb (double txpwr)
+{
+  m_txPwrDb = txpwr;
+}
+void
+UanPhyGen::SetRxThresholdDb (double thresh)
+{
+  m_rxThreshDb = thresh;
+}
+void
+UanPhyGen::SetCcaThresholdDb (double thresh)
+{
+  m_ccaThreshDb = thresh;
+}
+double
+UanPhyGen::GetRxGainDb (void)
+{
+  return m_rxGainDb;
+}
+double
+UanPhyGen::GetTxPowerDb (void)
+{
+  return m_txPwrDb;
+
+}
+double
+UanPhyGen::GetRxThresholdDb (void)
+{
+  return m_rxThreshDb;
+}
+double
+UanPhyGen::GetCcaThresholdDb (void)
+{
+  return m_ccaThreshDb;
+}
+
+Ptr<UanChannel>
+UanPhyGen::GetChannel (void) const
+{
+  return m_channel;
+}
+
+Ptr<UanNetDevice>
+UanPhyGen::GetDevice (void)
+{
+  return m_device;
+}
+
+Ptr<UanTransducer>
+UanPhyGen::GetTransducer (void)
+{
+  return m_transducer;
+}
+void
+UanPhyGen::SetChannel (Ptr<UanChannel> channel)
+{
+  m_channel = channel;
+}
+
+void
+UanPhyGen::SetDevice (Ptr<UanNetDevice> device)
+{
+  m_device = device;
+}
+
+void
+UanPhyGen::SetMac (Ptr<UanMac> mac)
+{
+  m_mac = mac;
+}
+
+void
+UanPhyGen::SetTransducer (Ptr<UanTransducer> trans)
+{
+  m_transducer = trans;
+  m_transducer->AddPhy (this);
+}
+
+
+void
+UanPhyGen::NotifyTransStartTx (Ptr<Packet> packet, double txPowerDb, UanTxMode txMode)
+{
+  if (m_pktRx)
+    {
+      m_minRxSinrDb = -1e30;
+    }
+}
+
+void
+UanPhyGen::NotifyIntChange (void)
+{
+  if (m_state == CCABUSY && GetInterferenceDb (Ptr<Packet> ()) < m_ccaThreshDb)
+    {
+      m_state = IDLE;
+      NotifyListenersCcaEnd ();
+    }
+}
+
+double
+UanPhyGen::CalculateSinrDb (Ptr<Packet> pkt, Time arrTime, double rxPowerDb, UanTxMode mode, UanPdp pdp)
+{
+  double noiseDb = m_channel->GetNoiseDbHz ( (double) mode.GetCenterFreqHz () / 1000.0) + 10 * log10 (mode.GetBandwidthHz ());
+  return m_sinr->CalcSinrDb (pkt, arrTime, rxPowerDb, noiseDb, mode, pdp, m_transducer->GetArrivalList ());
+}
+
+double
+UanPhyGen::GetInterferenceDb (Ptr<Packet> pkt)
+{
+
+  const UanTransducer::ArrivalList &arrivalList = m_transducer->GetArrivalList ();
+
+  UanTransducer::ArrivalList::const_iterator it = arrivalList.begin ();
+
+  double interfPower = 0;
+
+  for (; it != arrivalList.end (); it++)
+    {
+      if (pkt != it->GetPacket ())
+        {
+          interfPower += DbToKp (it->GetRxPowerDb ());
+        }
+    }
+
+  return KpToDb (interfPower);
+
+}
+
+double
+UanPhyGen::DbToKp (double db)
+{
+  return pow (10, db / 10.0);
+}
+double
+UanPhyGen::KpToDb (double kp)
+{
+  return 10 * log10 (kp);
+}
+
+void
+UanPhyGen::NotifyListenersRxStart (void)
+{
+  ListenerList::const_iterator it = m_listeners.begin ();
+  for (; it != m_listeners.end (); it++)
+    {
+      (*it)->NotifyRxStart ();
+    }
+
+}
+void
+UanPhyGen::NotifyListenersRxGood (void)
+{
+  ListenerList::const_iterator it = m_listeners.begin ();
+  for (; it != m_listeners.end (); it++)
+    {
+      (*it)->NotifyRxEndOk ();
+    }
+}
+void
+UanPhyGen::NotifyListenersRxBad (void)
+{
+  ListenerList::const_iterator it = m_listeners.begin ();
+  for (; it != m_listeners.end (); it++)
+    {
+      (*it)->NotifyRxEndError ();
+    }
+}
+void
+UanPhyGen::NotifyListenersCcaStart (void)
+{
+  ListenerList::const_iterator it = m_listeners.begin ();
+  for (; it != m_listeners.end (); it++)
+    {
+      (*it)->NotifyCcaStart ();
+    }
+}
+void
+UanPhyGen::NotifyListenersCcaEnd (void)
+{
+  ListenerList::const_iterator it = m_listeners.begin ();
+  for (; it != m_listeners.end (); it++)
+    {
+      (*it)->NotifyCcaEnd ();
+    }
+}
+
+void
+UanPhyGen::NotifyListenersTxStart (Time duration)
+{
+  ListenerList::const_iterator it = m_listeners.begin ();
+  for (; it != m_listeners.end (); it++)
+    {
+      (*it)->NotifyTxStart (duration);
+    }
+}
+
+uint32_t
+UanPhyGen::GetNModes (void)
+{
+  return m_modes.GetNModes ();
+}
+
+UanTxMode
+UanPhyGen::GetMode (uint32_t n)
+{
+  NS_ASSERT (n < m_modes.GetNModes ());
+
+  return m_modes[n];
+}
+
+Ptr<Packet>
+UanPhyGen::GetPacketRx (void) const
+{
+  return m_pktRx;
+}
+
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-phy-gen.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,259 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANPHYGEN_H
+#define UANPHYGEN_H
+
+
+#include "uan-phy.h"
+#include "ns3/traced-callback.h"
+#include "ns3/nstime.h"
+#include <list>
+
+namespace ns3 {
+namespace uan {
+
+/**
+ * \class UanPhyPerGenDefault
+ * \brief Default Packet Error Rate calculator for UanPhyGen
+ * Considers no error if SINR is > user defined threshold
+ * (configured by an attribute).
+ */
+class UanPhyPerGenDefault : public UanPhyPer
+{
+public:
+  UanPhyPerGenDefault ();
+  virtual ~UanPhyPerGenDefault ();
+
+  static TypeId GetTypeId (void);
+  virtual double CalcPer (Ptr<Packet> pkt, double sinrDb, UanTxMode mode);
+private:
+  double m_thresh;
+
+};
+
+/**
+ * \class UanPhyPerUmodem
+ * \brief Packet error rate calculation assuming WHOI Micromodem like PHY
+ * Calculates PER assuming rate 1/2 convolutional code with constraint length 9
+ * with soft decision viterbi decoding and a CRC capable of correcting 1 bit error
+ */
+class UanPhyPerUmodem : public UanPhyPer
+{
+public:
+  UanPhyPerUmodem ();
+  virtual ~UanPhyPerUmodem ();
+
+  static TypeId GetTypeId (void);
+
+  /**
+   * 
+   * This implementation uses calculations 
+   * for binary FSK modulation coded by a rate 1/2 convolutional code 
+   * with constraint length = 9 and a viterbi decoder and finally a CRC capable 
+   * of correcting one bit error.  These equations can be found in
+   * the book, Digital Communications, by Proakis (Any version I think)
+   * 
+   * \param pkt Packet which is under consideration
+   * \param sinrDb SINR at receiver
+   * \param mode TX mode used to transmit packet
+   * \returns Probability of packet error
+   */
+  virtual double CalcPer (Ptr<Packet> pkt, double sinrDb, UanTxMode mode);
+private:
+  double NChooseK (uint32_t n, uint32_t k);
+
+};
+/**
+ * \class UanPhyCalcSinrDefault
+ * \brief Default SINR calculator for UanPhyGen
+ * The default ignores mode data and assumes that all rxpower transmitted is
+ * captured by the receiver, and that all signal power associated with
+ * interfering packets affects SINR identically to additional ambient noise.
+ */
+class UanPhyCalcSinrDefault : public UanPhyCalcSinr
+{
+
+public:
+  UanPhyCalcSinrDefault ();
+  virtual ~UanPhyCalcSinrDefault ();
+  static TypeId GetTypeId (void);
+  /** 
+   * This implementation simply adds all arriving signal power
+   * and assumes it acts identically to additional noise.
+   * 
+   * \param pkt Packet which is under consideration
+   * \param arrTime Arrival time of packet pkt
+   * \param rxPowerDb Received signal power at receiver
+   * \param ambNoiseDb Ambient channel noise in dB re 1 uPa
+   * \param mode TX mode used to transmit packet
+   * \param pdp Power delay profile of arriving packet pkt
+   * \param arrivalList List of other, simultaneously arriving packets
+   * \returns Probability of packet error
+   */
+  virtual double CalcSinrDb (Ptr<Packet> pkt,
+                             Time arrTime,
+                             double rxPowerDb,
+                             double ambNoiseDb,
+                             UanTxMode mode,
+                             UanPdp pdp,
+                             const UanTransducer::ArrivalList &arrivalList
+                             ) const;
+};
+
+/**
+ * \class UanPhyCalcSinrFhFsk
+ * \brief WHOI Micromodem like FH-FSK model
+ *
+ * Model of interference calculation for FH-FSK wherein all nodes
+ * use an identical hopping pattern.  In this case, there is an (M-1)*SymbolTime
+ * clearing time between symbols transmitted on the same frequency.
+ * This clearing time combats ISI from channel delay spread and also has
+ * a byproduct of possibly reducing interference from other transmitted packets.
+ */
+class UanPhyCalcSinrFhFsk : public UanPhyCalcSinr
+{
+
+public:
+  UanPhyCalcSinrFhFsk ();
+  virtual ~UanPhyCalcSinrFhFsk ();
+  static TypeId GetTypeId (void);
+  virtual double CalcSinrDb (Ptr<Packet> pkt,
+                             Time arrTime,
+                             double rxPowerDb,
+                             double ambNoiseDb,
+                             UanTxMode mode,
+                             UanPdp pdp,
+                             const UanTransducer::ArrivalList &arrivalList
+                             ) const;
+private:
+  uint32_t m_hops;
+};
+
+/**
+ * \class UanPhyGen
+ * \brief Generic PHY model
+ *
+ * This is a generic PHY class.  SINR and PER information
+ * are controlled via attributes.  By adapting the SINR
+ * and PER models to a specific situation, this PHY should
+ * be able to model a wide variety of networks.
+ */
+class UanPhyGen : public UanPhy
+{
+public:
+  UanPhyGen ();
+  virtual ~UanPhyGen ();
+  /**
+   * \returns Default TX modes of UanPhyGen
+   */
+  static UanModesList GetDefaultModes (void);
+
+  static TypeId GetTypeId (void);
+  virtual void SendPacket (Ptr<Packet> pkt, uint32_t modeNum);
+  virtual void RegisterListener (UanPhyListener *listener);
+  virtual void StartRxPacket (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp);
+  virtual void SetReceiveOkCallback (RxOkCallback cb);
+  virtual void SetReceiveErrorCallback (RxErrCallback cb);
+  virtual bool IsStateIdle (void);
+  virtual bool IsStateBusy (void);
+  virtual bool IsStateRx (void);
+  virtual bool IsStateTx (void);
+  virtual bool IsStateCcaBusy (void);
+  virtual void SetRxGainDb (double gain);
+  virtual void SetTxPowerDb (double txpwr);
+  virtual void SetRxThresholdDb (double thresh);
+  virtual void SetCcaThresholdDb (double thresh);
+  virtual double GetRxGainDb (void);
+  virtual double GetTxPowerDb (void);
+  virtual double GetRxThresholdDb (void);
+  virtual double GetCcaThresholdDb (void);
+  virtual Ptr<UanChannel> GetChannel (void) const;
+  virtual Ptr<UanNetDevice> GetDevice (void);
+  virtual Ptr<UanTransducer> GetTransducer (void);
+  virtual void SetChannel (Ptr<UanChannel> channel);
+  virtual void SetDevice (Ptr<UanNetDevice> device);
+  virtual void SetMac (Ptr<UanMac> mac);
+  virtual void SetTransducer (Ptr<UanTransducer> trans);
+  virtual void NotifyTransStartTx (Ptr<Packet> packet, double txPowerDb, UanTxMode txMode);
+  virtual void NotifyIntChange (void);
+  virtual uint32_t GetNModes (void);
+  virtual UanTxMode GetMode (uint32_t n);
+  virtual Ptr<Packet> GetPacketRx (void) const;
+  virtual void Clear (void);
+
+private:
+  typedef std::list<UanPhyListener *> ListenerList;
+
+  UanModesList m_modes;
+
+  State m_state;
+  ListenerList m_listeners;
+  RxOkCallback m_recOkCb;
+  RxErrCallback m_recErrCb;
+  Ptr<UanChannel> m_channel;
+  Ptr<UanTransducer> m_transducer;
+  Ptr<UanNetDevice> m_device;
+  Ptr<UanMac> m_mac;
+  Ptr<UanPhyPer> m_per;
+  Ptr<UanPhyCalcSinr> m_sinr;
+
+  double m_rxGainDb;
+  double m_txPwrDb;
+  double m_rxThreshDb;
+  double m_ccaThreshDb;
+
+
+  Ptr<Packet> m_pktRx;
+  double m_minRxSinrDb;
+  double m_rxRecvPwrDb;
+  Time m_pktRxArrTime;
+  UanPdp m_pktRxPdp;
+  UanTxMode m_pktRxMode;
+
+  bool m_cleared;
+
+  TracedCallback<Ptr<const Packet>, double, UanTxMode > m_rxOkLogger;
+  TracedCallback<Ptr<const Packet>, double, UanTxMode > m_rxErrLogger;
+  TracedCallback<Ptr<const Packet>, double, UanTxMode > m_txLogger;
+
+
+  double CalculateSinrDb (Ptr<Packet> pkt, Time arrTime, double rxPowerDb, UanTxMode mode, UanPdp pdp);
+  double GetInterferenceDb (Ptr<Packet> pkt);
+  double DbToKp (double db);
+  double KpToDb (double kp);
+  void RxEndEvent (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode);
+  void TxEndEvent ();
+
+  void NotifyListenersRxStart (void);
+  void NotifyListenersRxGood (void);
+  void NotifyListenersRxBad (void);
+  void NotifyListenersCcaStart (void);
+  void NotifyListenersCcaEnd (void);
+  void NotifyListenersTxStart (Time duration);
+protected:
+  virtual void DoDispose ();
+
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANPHYGEN_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-phy.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,51 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-phy.h"
+
+namespace ns3 {
+namespace uan {
+
+void
+UanPhyCalcSinr::Clear ()
+{
+}
+
+void
+UanPhyCalcSinr::DoDispose ()
+{
+  Clear ();
+  Object::DoDispose ();
+}
+
+void
+UanPhyPer::Clear ()
+{
+}
+
+void
+UanPhyPer::DoDispose ()
+{
+  Clear ();
+  Object::DoDispose ();
+}
+
+} // namespace uan
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-phy.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,362 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+
+#ifndef UANPHY_H
+#define UANPHY_H
+
+#include "ns3/object.h"
+#include "uan-mac.h"
+#include "uan-tx-mode.h"
+#include "uan-prop-model.h"
+#include "uan-transducer.h"
+
+namespace ns3 {
+namespace uan {
+
+
+/**
+ * \class UanPhyCalcSinr
+ *
+ * Class used for calculating SINR of packet in UanPhy.
+ * Can be set to any derived class using attributes of UanPhy
+ * to implement different models.
+ */
+class UanPhyCalcSinr : public Object
+{
+
+public:
+  /**
+   * \param pkt Packet to calculate SINR for
+   * \param arrTime Arrival time of pkt
+   * \param rxPowerDb The received signal strength of the packet in dB re 1 uPa
+   * \param ambNoiseDb Ambient channel noise in dB re 1 uPa
+   * \param mode TX Mode of pkt
+   * \param pdp  Power delay profile of pkt
+   * \param arrivalList  List of interfering arrivals given from Transducer.
+   */
+  virtual double CalcSinrDb (Ptr<Packet> pkt,
+                             Time arrTime,
+                             double rxPowerDb,
+                             double ambNoiseDb,
+                             UanTxMode mode,
+                             UanPdp pdp,
+                             const UanTransducer::ArrivalList &arrivalList
+                             ) const = 0;
+  /**
+   * Clears all pointer references
+   */
+  virtual void Clear (void);
+
+  virtual void DoDispose (void);
+
+  /**
+   * \param db dB value
+   * \returns kilopascals 
+   * \brief Converts dB re 1 uPa to kilopascals
+   */
+  inline double DbToKp (double db) const
+  {
+    return pow (10, db / 10.0);
+  }
+  /**
+   * \param kp value in kilopascals
+   * \returns dB re 1 uPa
+   * \brief Converts kilopascals to dB re 1 uPa
+   */
+  inline double KpToDb (double kp) const
+  {
+    return 10 * log10 (kp);
+  }
+  
+};
+
+/**
+ * \class UanPhyPer
+ * Used in UanPhy for determining probability of packet error based on received SINR and
+ * modulation (mode).  Can be set in UanPhy via attributes
+ */
+class UanPhyPer : public Object
+{
+public:
+  /**
+   * Calculates the prob. of packet error based on
+   * SINR at the receiver and a tx mode.
+   * \param pkt Packet which is under consideration
+   * \param sinrDb SINR at receiver
+   * \param mode TX mode used to transmit packet
+   * \returns Probability of packet error
+   */
+  virtual double CalcPer (Ptr<Packet> pkt, double sinrDb, UanTxMode mode) = 0;
+  /**
+   * Clears all pointer references
+   */
+  virtual void Clear (void);
+
+  virtual void DoDispose (void);
+};
+
+
+/**
+ * \class UanPhyListener
+ *
+ * \brief Interface for PHY event listener
+ * A class which implements this interface may register with Phy object
+ * to receive notification of TX/RX/CCA events
+ */
+class UanPhyListener
+{
+public:
+  virtual ~UanPhyListener () {}
+  /**
+   * \brief Function called when Phy object begins receiving packet
+   */
+  virtual void NotifyRxStart (void) = 0;
+  /**
+   * \brief Function called when Phy object finishes receiving packet without error
+   */
+  virtual void NotifyRxEndOk (void) = 0;
+  /**
+   * \brief Function called when Phy object finishes receiving packet in error
+   */
+  virtual void NotifyRxEndError (void) = 0;
+  /**
+   * \brief Function called when Phy object begins sensing channel is busy
+   */
+  virtual void NotifyCcaStart (void) = 0;
+  /**
+   * \brief Function called when Phy object stops sensing channel is busy
+   */
+  virtual void NotifyCcaEnd (void) = 0;
+  /**
+   * \param duration Duration of transmission
+   * \brief Function called when transmission starts from Phy object
+   */
+  virtual void NotifyTxStart (Time duration) = 0;
+};
+
+/**
+ * \class UanPhy
+ *
+ * \brief Base class for UAN Phy models
+ */
+class UanPhy : public Object
+{
+public:
+  /// Enum defining possible Phy states
+  enum State {
+    IDLE, CCABUSY, RX, TX
+  };
+
+  /**
+   * arg1: packet received successfully
+   * arg2: snr of packet
+   * arg3: mode of packet
+   */
+  typedef Callback<void, Ptr<Packet>, double, UanTxMode> RxOkCallback;
+
+  /**
+   * arg1: packet received successfully
+   * arg2: snr of packet
+   */
+  typedef Callback<void, Ptr<Packet>, double > RxErrCallback;
+
+  /**
+   * \param pkt  Packet to transmit
+   * \param modeNum  Index of mode in SupportedModes list to use for transmission
+   */
+  virtual void SendPacket (Ptr<Packet> pkt, uint32_t modeNum) = 0;
+
+  /**
+   * \param listener New listener to register
+   *
+   * Register an object to be notified of common Phy events
+   */
+  virtual void RegisterListener (UanPhyListener *listener) = 0;
+
+  /**
+   * \brief Packet arriving from channel:  i.e.  leading bit of packet has arrived.
+   * \param pkt Packet which is arriving
+   * \param rxPowerDb Signal power of incoming packet in dB
+   * \param txMode Transmission mode defining modulation of incoming packet
+   * \param pdp Power delay profile of incoming packet
+   */
+  virtual void StartRxPacket (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp) = 0;
+
+  /**
+   * \param cb Callback to be enabled when packet is received without error
+   */
+  virtual void SetReceiveOkCallback (RxOkCallback cb) = 0;
+
+  /**
+   * \param cb Callback to be enabled when a packet is received with errors
+   */
+  virtual void SetReceiveErrorCallback (RxErrCallback cb) = 0;
+
+  /**
+   * \param gain Gain added at receiver
+   */
+
+  virtual void SetRxGainDb (double gain) = 0;
+
+  /**
+   * \param txpwr Final output transmission power in dB
+   */
+  virtual void SetTxPowerDb (double txpwr) = 0;
+
+  /**
+   * \param thresh Threshold SINR for propper reception in dB
+   */
+  virtual void SetRxThresholdDb (double thresh) = 0;
+
+  /**
+   * \param thresh Signal power at receiver required for CCA busy state
+   *
+   */
+  virtual void SetCcaThresholdDb (double thresh) = 0;
+
+  /**
+   * \returns Gain added to signal at receiver in dB
+   */
+  virtual double GetRxGainDb (void) = 0;
+
+  /**
+   * \returns Current TX power output
+   */
+  virtual double GetTxPowerDb (void) = 0;
+
+  /**
+   * \returns Required signal strength, in dB, to begin receiving packet
+   */
+  virtual double GetRxThresholdDb (void) = 0;
+
+  /**
+   * \returns Threshold signal strength in dB to enter CCA busy mode
+   */
+  virtual double GetCcaThresholdDb (void) = 0;
+
+  /**
+   *
+   * \returns True if Phy is IDLE
+   */
+  virtual bool IsStateIdle (void) = 0;
+  /**
+   *
+   * \returns True if Phy is not IDLE
+   */
+  virtual bool IsStateBusy (void) = 0;
+  /**
+   *
+   * \returns True if Phy is currently in receive mode
+   */
+  virtual bool IsStateRx (void) = 0;
+  /**
+   *
+   * \returns True if Phy is busy transmitting
+   */
+  virtual bool IsStateTx (void) = 0;
+  /**
+   *
+   * \returns True if Phy is not TX or RX but the channel is sensed busy
+   */
+  virtual bool IsStateCcaBusy (void) = 0;
+
+  /**
+   * \returns Channel this phy is attached to
+   */
+  virtual Ptr<UanChannel> GetChannel (void) const = 0;
+
+  /**
+   * \returns the Net Device that this Phy is a part of
+   */
+  virtual Ptr<UanNetDevice> GetDevice (void) = 0;
+
+  /**
+   * \param channel The channel this Phy is attached to
+   */
+  virtual void SetChannel (Ptr<UanChannel> channel) = 0;
+
+  /**
+   * \param device The Net Device this Phy is a part of
+   */
+  virtual void SetDevice (Ptr<UanNetDevice> device) = 0;
+
+  /**
+   * \param mac The MAC forwarding messages to this Phy
+   */
+  virtual void SetMac (Ptr<UanMac> mac) = 0;
+
+  /**
+   * \param packet Packet that is beginning transmission
+   * \param txPowerDb Transmit power of packet
+   * \param txMode  Transmission mode of packet
+   *
+   * Notification that there is a transmission beginning
+   * on the transducer that this Phy is attached to.
+   */
+
+  virtual void NotifyTransStartTx (Ptr<Packet> packet, double txPowerDb, UanTxMode txMode) = 0;
+
+  /**
+   *
+   * Function called when there has been a change in the
+   * ammount of interference this node is experiencing
+   * from other transmissions
+   */
+  virtual void NotifyIntChange (void) = 0;
+
+  /**
+   *
+   * \param trans Transducer this Phy outputs to / receives from
+   */
+  virtual void SetTransducer (Ptr<UanTransducer> trans) = 0;
+
+  /**
+   * \returns Transducer this Phy outputs to / receives from
+   */
+  virtual Ptr<UanTransducer> GetTransducer (void) = 0;
+
+  /**
+   * \returns Number of TX modes supported by this PHY
+   */
+  virtual uint32_t GetNModes (void) = 0;
+
+  /**
+   * \param n Mode number of mode to return (place in Modeslist)
+   * \returns Mode n
+   */
+  virtual UanTxMode GetMode (uint32_t n) = 0;
+
+  /**
+   * \warning Returns non-valid pointer if IsStateRx == false
+   * \returns Packet currently being received in PHY
+   */
+  virtual Ptr<Packet> GetPacketRx (void) const = 0;
+
+  /**
+   * Clears all pointer references
+   */
+  virtual void Clear (void) = 0;
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANPHY_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-prop-model-ideal.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,69 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-prop-model-ideal.h"
+#include "uan-tx-mode.h"
+#include "ns3/mobility-model.h"
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanPropModelIdeal);
+
+UanPropModelIdeal::UanPropModelIdeal ()
+{
+}
+
+UanPropModelIdeal::~UanPropModelIdeal ()
+{
+}
+
+TypeId
+UanPropModelIdeal::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanPropModelIdeal")
+    .SetParent<Object> ()
+    .AddConstructor<UanPropModelIdeal> ()
+  ;
+  return tid;
+}
+
+
+double
+UanPropModelIdeal::GetPathLossDb (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode)
+{
+
+  return 0;
+}
+UanPdp
+UanPropModelIdeal::GetPdp (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode)
+{
+  return UanPdp::CreateImpulsePdp ();
+}
+
+Time
+UanPropModelIdeal::GetDelay (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode)
+{
+  return Seconds (a->GetDistanceFrom (b) / 1500.0);
+}
+
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-prop-model-ideal.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,52 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANPROPMODELIDEAL_H_
+#define UANPROPMODELIDEAL_H_
+
+#include "uan-prop-model.h"
+#include "ns3/mobility-model.h"
+#include "ns3/nstime.h"
+namespace ns3 {
+namespace uan {
+
+/**
+ * \class UanPropModelIdeal
+ *
+ * \brief Ideal propagation model (no pathloss, impulse PDP)
+ */
+class UanPropModelIdeal : public UanPropModel
+{
+public:
+  UanPropModelIdeal ();
+  virtual ~UanPropModelIdeal ();
+
+  static TypeId GetTypeId (void);
+
+  // Inherited methods
+  virtual double GetPathLossDb (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode);
+  virtual UanPdp GetPdp (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode);
+  virtual Time GetDelay (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode);
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif /*UANPROPMODELIDEAL_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-prop-model-thorp.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,97 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+#include "uan-prop-model-thorp.h"
+#include "uan-tx-mode.h"
+#include "ns3/double.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("UanPropModelThorp");
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanPropModelThorp);
+
+UanPropModelThorp::UanPropModelThorp ()
+{
+}
+
+UanPropModelThorp::~UanPropModelThorp ()
+{
+}
+
+TypeId
+UanPropModelThorp::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UanPropModelThorp")
+    .SetParent<Object> ()
+    .AddConstructor<UanPropModelThorp> ()
+    .AddAttribute ("SpreadCoef",
+                   "Spreading coefficient used in calculation of Thorp's approximation",
+                   DoubleValue (1.5),
+                   MakeDoubleAccessor (&UanPropModelThorp::m_SpreadCoef),
+                   MakeDoubleChecker<double> ())
+  ;
+  return tid;
+}
+
+double
+UanPropModelThorp::GetPathLossDb (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode)
+{
+  double distKyd = a->GetDistanceFrom (b) / 1.093613298; // Convert from dB/km to dB/kyd
+
+  return m_SpreadCoef * 10.0 * log10 (distKyd)
+         + distKyd * GetAttenDbKyd (mode.GetCenterFreqHz () / 1000.0);
+}
+
+UanPdp
+UanPropModelThorp::GetPdp (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode)
+{
+  return UanPdp::CreateImpulsePdp ();
+}
+
+Time
+UanPropModelThorp::GetDelay (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode)
+{
+  return Seconds (a->GetDistanceFrom (b) / 1500.0);
+}
+
+double
+UanPropModelThorp::GetAttenDbKyd (double freqKhz)
+{
+
+  double fsq = freqKhz * freqKhz;
+  double atten;
+
+  if (freqKhz < 0.4)
+    {
+      atten = 0.11 * fsq / (1 + fsq) + 44 * fsq / (4100 + freqKhz)
+        + 2.75 * 0.0001 * fsq + 0.003;
+    }
+  else
+    {
+      atten = 0.002 + 0.11 * (freqKhz / (1 + freqKhz)) + 0.011 * freqKhz;
+    }
+
+  return atten;
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-prop-model-thorp.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,56 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANPROPMODELTHORP_H_
+#define UANPROPMODELTHORP_H_
+
+#include "uan-prop-model.h"
+
+namespace ns3 {
+namespace uan {
+
+class UanTxMode;
+
+/**
+ * \class UanPropModelThorp
+ * \brief Uses Thorp's approximation to compute pathloss.  Assumes implulse PDP.
+ */
+class UanPropModelThorp : public UanPropModel
+{
+public:
+  UanPropModelThorp ();
+  virtual ~UanPropModelThorp ();
+
+  static TypeId GetTypeId (void);
+
+  virtual double GetPathLossDb (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode);
+  virtual UanPdp GetPdp (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode);
+  virtual Time GetDelay (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode);
+
+private:
+  double GetAttenDbKyd (double freqKhz);
+
+  double m_SpreadCoef;
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif /* UANPROPMODELTHORP_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-prop-model.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,354 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-prop-model.h"
+#include "ns3/nstime.h"
+#include <complex>
+#include <vector>
+
+
+namespace ns3 {
+namespace uan {
+
+std::ostream &
+operator<< (std::ostream &os, UanPdp &pdp)
+{
+  os << pdp.GetNTaps () << '|';
+  os << pdp.GetResolution ().GetSeconds () << '|';
+
+  UanPdp::Iterator it = pdp.m_taps.begin ();
+  for (; it != pdp.m_taps.end (); it++)
+    {
+      os << (*it).GetAmp () << '|';
+    }
+  return os;
+
+}
+std::istream &
+operator>> (std::istream &is, UanPdp &pdp)
+{
+  uint32_t ntaps;
+  double resolution;
+  char c1;
+
+  is >> ntaps >> c1;
+  if (c1 != '|')
+    {
+      NS_FATAL_ERROR ("UanPdp data corrupted at # of taps");
+      return is;
+    }
+  is >> resolution >> c1;
+  if (c1 != '|')
+    {
+      NS_FATAL_ERROR ("UanPdp data corrupted at resolution");
+      return is;
+    }
+  pdp.m_resolution = Seconds (resolution);
+
+
+  std::complex<double> amp;
+  pdp.m_taps = std::vector<Tap> (ntaps);
+  for (uint32_t i = 0; i < ntaps; i++)
+    {
+      is >> amp >> c1;
+      if (c1 != '|')
+        {
+          NS_FATAL_ERROR ("UanPdp data corrupted at tap " << i);
+          return is;
+        }
+      pdp.m_taps[i] = Tap (Seconds (resolution * i), amp);
+    }
+  return is;
+
+}
+
+Tap::Tap ()
+  : m_amplitude (0.0),
+    m_delay (Seconds (0))
+{
+
+}
+
+Tap::Tap (Time delay, std::complex<double> amp)
+  : m_amplitude (amp),
+    m_delay (delay)
+{
+
+}
+
+std::complex<double>
+Tap::GetAmp (void) const
+{
+  return m_amplitude;
+}
+
+Time
+Tap::GetDelay (void) const
+{
+  return m_delay;
+}
+
+
+UanPdp::UanPdp ()
+{
+
+}
+
+UanPdp::UanPdp (std::vector<Tap> taps, Time resolution)
+  : m_taps (taps),
+    m_resolution (resolution)
+{
+}
+
+UanPdp::UanPdp (std::vector<std::complex<double> > amps, Time resolution)
+  : m_resolution (resolution)
+{
+  m_taps.resize (amps.size ());
+  Time arrTime = Seconds (0);
+  for (uint32_t index = 0; index < amps.size (); index++)
+    {
+      m_taps[index] = Tap (arrTime, amps[index]);
+      arrTime = arrTime + m_resolution;
+    }
+}
+
+UanPdp::UanPdp (std::vector<double> amps, Time resolution)
+  : m_resolution (resolution)
+{
+  m_taps.resize (amps.size ());
+  Time arrTime = Seconds (0);
+  for (uint32_t index = 0; index < amps.size (); index++)
+    {
+      m_taps[index] = Tap (arrTime, amps[index]);
+      arrTime = arrTime + m_resolution;
+    }
+}
+
+UanPdp::~UanPdp ()
+{
+  m_taps.clear ();
+}
+
+void
+UanPdp::SetTap (std::complex<double> amp, uint32_t index)
+{
+  if (m_taps.size () <= index)
+    {
+      m_taps.resize (index + 1);
+    }
+
+  Time delay = Seconds (index * m_resolution.GetSeconds ());
+  m_taps[index] = Tap (delay, amp);
+}
+const Tap &
+UanPdp::GetTap (uint32_t i) const
+{
+  NS_ASSERT_MSG (i < GetNTaps (), "Call to UanPdp::GetTap with requested tap out of range");
+  return m_taps[i];
+}
+void
+UanPdp::SetNTaps (uint32_t nTaps)
+{
+  m_taps.resize (nTaps);
+}
+void
+UanPdp::SetResolution (Time resolution)
+{
+  m_resolution = resolution;
+}
+UanPdp::Iterator
+UanPdp::GetBegin (void) const
+{
+  return m_taps.begin ();
+}
+
+UanPdp::Iterator
+UanPdp::GetEnd (void) const
+{
+  return m_taps.end ();
+}
+
+uint32_t
+UanPdp::GetNTaps (void) const
+{
+  return m_taps.size ();
+}
+
+Time
+UanPdp::GetResolution (void) const
+{
+  return m_resolution;
+}
+
+std::complex<double>
+UanPdp::SumTapsFromMaxC (Time delay, Time duration) const
+{
+  if (m_resolution <= Seconds (0))
+    {
+      NS_ASSERT_MSG (GetNTaps () == 1, "Attempted to sum taps over time interval in "
+                     "UanPdp with resolution 0 and multiple taps");
+
+      return m_taps[0].GetAmp ();
+    }
+
+  uint32_t numTaps =  static_cast<uint32_t> (duration.GetSeconds () / m_resolution.GetSeconds () + 0.5);
+  double maxAmp = -1;
+  uint32_t maxTapIndex = 0;
+
+  for (uint32_t i = 0; i < GetNTaps (); i++)
+    {
+      if (abs (m_taps[i].GetAmp ()) > maxAmp)
+        {
+          maxAmp = abs (m_taps[i].GetAmp ());
+          maxTapIndex = i;
+        }
+    }
+  uint32_t start = maxTapIndex + static_cast<uint32_t> (delay.GetSeconds () / m_resolution.GetSeconds ());
+  uint32_t end = std::min (start + numTaps, GetNTaps ());
+  std::complex<double> sum = 0;
+  for (uint32_t i = start; i < end; i++)
+    {
+      sum += m_taps[i].GetAmp ();
+    }
+  return sum;
+}
+double
+UanPdp::SumTapsFromMaxNc (Time delay, Time duration) const
+{
+  if (m_resolution <= Seconds (0))
+    {
+      NS_ASSERT_MSG (GetNTaps () == 1, "Attempted to sum taps over time interval in "
+                     "UanPdp with resolution 0 and multiple taps");
+
+      return abs (m_taps[0].GetAmp ());
+    }
+
+  uint32_t numTaps =  static_cast<uint32_t> (duration.GetSeconds () / m_resolution.GetSeconds () + 0.5);
+  double maxAmp = -1;
+  uint32_t maxTapIndex = 0;
+
+  for (uint32_t i = 0; i < GetNTaps (); i++)
+    {
+      if (abs (m_taps[i].GetAmp ()) > maxAmp)
+        {
+          maxAmp = abs (m_taps[i].GetAmp ());
+          maxTapIndex = i;
+        }
+    }
+
+
+  uint32_t start = maxTapIndex + static_cast<uint32_t> (delay.GetSeconds () / m_resolution.GetSeconds ());
+  uint32_t end = std::min (start + numTaps, GetNTaps ());
+  double sum = 0;
+  for (uint32_t i = start; i < end; i++)
+
+    {
+      sum += abs (m_taps[i].GetAmp ());
+    }
+  return sum;
+}
+double
+UanPdp::SumTapsNc (Time begin, Time end) const
+{
+  if (m_resolution <= Seconds (0))
+    {
+      NS_ASSERT_MSG (GetNTaps () == 1, "Attempted to sum taps over time interval in "
+                     "UanPdp with resolution 0 and multiple taps");
+
+      if (begin <= Seconds (0.0) && end >= Seconds (0.0))
+        {
+          return abs (m_taps[0].GetAmp ());
+        }
+      else
+        {
+          return 0.0;
+        }
+    }
+
+  uint32_t stIndex = (uint32_t)(begin.GetSeconds () / m_resolution.GetSeconds () + 0.5);
+  uint32_t endIndex = (uint32_t)(end.GetSeconds () / m_resolution.GetSeconds () + 0.5);
+
+  endIndex = std::min (endIndex, GetNTaps ());
+  double sum = 0;
+  for (uint32_t i = stIndex; i < endIndex; i++)
+    {
+      sum += abs (m_taps[i].GetAmp ());
+    }
+  return sum;
+
+}
+
+
+
+std::complex<double>
+UanPdp::SumTapsC (Time begin, Time end) const
+{
+  if (m_resolution <= Seconds (0))
+    {
+      NS_ASSERT_MSG (GetNTaps () == 1, "Attempted to sum taps over time interval in "
+                     "UanPdp with resolution 0 and multiple taps");
+
+      if (begin <= Seconds (0.0) && end >= Seconds (0.0))
+        {
+          return m_taps[0].GetAmp ();
+        }
+      else
+        {
+          return std::complex<double> (0.0);
+        }
+    }
+
+  uint32_t stIndex = (uint32_t)(begin.GetSeconds () / m_resolution.GetSeconds () + 0.5);
+  uint32_t endIndex = (uint32_t)(end.GetSeconds () / m_resolution.GetSeconds () + 0.5);
+
+  endIndex = std::min (endIndex, GetNTaps ());
+
+  std::complex<double> sum = 0;
+  for (uint32_t i = stIndex; i < endIndex; i++)
+    {
+      sum += m_taps[i].GetAmp ();
+    }
+  return sum;
+}
+
+UanPdp
+UanPdp::CreateImpulsePdp (void)
+{
+  UanPdp pdp;
+  pdp.SetResolution (Seconds (0));
+  pdp.SetTap (1.0,0);
+  return pdp;
+}
+
+void
+UanPropModel::Clear (void)
+{
+}
+
+void
+UanPropModel::DoDispose (void)
+{
+  Clear ();
+  Object::DoDispose ();
+}
+
+} // namespace uan
+} // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-prop-model.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,256 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANPROPMODEL_H_
+#define UANPROPMODEL_H_
+
+#include "ns3/object.h"
+#include "ns3/mobility-model.h"
+#include "ns3/nstime.h"
+
+
+#include <vector>
+#include <complex>
+#include <utility>
+
+namespace ns3 {
+namespace uan {
+
+class UanTxMode;
+
+/**
+ * \class Tap
+ * \brief Holds PDP Tap information (amplitude and delay)
+ */
+class Tap
+{
+public:
+  /**
+   * Default constructor.  Creates Tap with delay=0, amp=0
+   */
+  Tap ();
+  /**
+   * \param delay Time delay (usually from first arrival) of signal
+   * \param amp Complex amplitude of arrival
+   */
+  Tap (Time delay, std::complex<double> amp);
+  /**
+   * \returns Complex amplitude of arrival
+   */
+  std::complex<double> GetAmp (void) const;
+  /**
+   * \returns Time delay (usually from first arrival) of signal
+   */
+  Time GetDelay (void) const;
+
+private:
+  std::complex<double> m_amplitude;
+  Time m_delay;
+};
+
+/**
+ * \class UanPdp
+ *
+ * Container class to describe power delay profile returned
+ * from UAN propagation models using tapped delay line model.
+ * This should model a channel impulse response as a set of
+ * equally spaced signal arrivals.
+ *
+ * Generally, the profile should be normalized, such that
+ * the sum of all taps should equal 1.  The received signal
+ * power on any interval (t1, t2) can then be found from
+ * summing the taps on the interval and multiplying by
+ * the total received power at the receiver.
+ *
+ *
+ */
+class UanPdp
+{
+public:
+  /**
+   * \brief Iterator is a standard template library constant interator
+   */
+  typedef std::vector<Tap>::const_iterator Iterator;
+  /**
+   * \brief Create empty PDP object
+   */
+  UanPdp ();
+  /**
+   * \brief Create PDP object from a vector of Tap objects
+   * \param taps Taps to include in this PDP
+   * \param resolution Resolution of PDP object
+   */
+  UanPdp (std::vector<Tap> taps, Time resolution);
+  /**
+   * \brief Create PDP object from vector of arrival amplitudes
+   * \param arrivals  Vector of complex amplitude arrivals
+   * \param resolution Time duration between arrivals in vector
+   */
+  UanPdp (std::vector<std::complex<double > > arrivals, Time resolution);
+  /**
+   * \brief Create PDP object from real valued arrival amplitudes
+   * \param arrivals vector of real valued arrivals
+   * \param resolution Time duration between arrivals in vector
+   */
+  UanPdp (std::vector<double> arrivals, Time resolution);
+  ~UanPdp ();
+
+  /**
+   * \param arrival complex arrival value
+   * \param index index of arrival
+   */
+  void SetTap (std::complex<double> arrival, uint32_t index);
+  /**
+   * \param nTaps number of taps in this PDP
+   */
+  void SetNTaps (uint32_t nTaps);
+  /**
+   * \param resolution Resolution of PDP (time between arrivals)
+   */
+  void SetResolution (Time resolution);
+  /**
+   * \returns Iterator positioned at first arrival
+   */
+  Iterator GetBegin (void) const;
+  /**
+   * \returns Iterator positioned after last arrival
+   */
+  Iterator GetEnd (void) const;
+  /**
+   * \returns Number of taps in PDP
+   */
+  uint32_t GetNTaps (void) const;
+  /**
+   * \returns Tap object at index i
+   * \param i Index number of tap to return (0 based)
+   */
+  const Tap &GetTap (uint32_t i) const;
+  /**
+   * \returns Resolution of PDP (time duration between arrivals)
+   */
+  Time GetResolution (void) const;
+  /**
+   * \param begin Time value to begin summing arrivals
+   * \param end Time value to end summing arrivals
+   * \returns Returns Non-coherent sum of arrivals between two time values
+   *
+   * Assuming that Tap at index 0 arrives at time 0,
+   * this function sums non-coherently (sums amplitude of arrivals
+   * ignoring phase difference) all arrivals between a start
+   * and end time.
+   */
+  double SumTapsNc (Time begin, Time end) const;
+  /**
+   * \param begin Time value to begin summing arrivals
+   * \param end Time value to end summing arrivals
+   * \returns Returns coherent sum of arrivals between two time values
+   *
+   * Assuming that Tap at index 0 arrives at time 0,
+   * this function sums coherently (sums amplitude of arrivals
+   * considering phase difference) all arrivals between a start
+   * and end time.
+   */
+  std::complex<double> SumTapsC (Time begin, Time end) const;
+  /**
+   * \param delay Time duratation after max to begin summing arrivals
+   * \param duration Time duration to sum arrivals for
+   * \returns non-coherent sum of arrivals after max in given window
+   *
+   * this function sums non-coherently (sums amplitude of arrivals
+   * ignoring phase difference) all arrivals in a given duration
+   * starting the given time after the maximum amplitude arrival received
+   */
+  double SumTapsFromMaxNc (Time delay, Time duration) const;
+  /**
+   * \param delay Time duratation after max to begin summing arrivals
+   * \param duration Time duration to sum arrivals for
+   * \returns coherent sum of arrivals after max in given window
+   *
+   * this function sums coherently (sums amplitude of arrivals
+   * considering phase difference) all arrivals in a given duration
+   * starting the given time after the maximum amplitude arrival received
+   */
+  std::complex<double> SumTapsFromMaxC (Time delay, Time duration) const;
+
+  /**
+   * \returns A PDP with a singlue unit impulse arrival at time 0
+   */ 
+  static UanPdp CreateImpulsePdp (void);
+private:
+  friend std::ostream &operator<< (std::ostream &os, UanPdp &pdp);
+  friend std::istream &operator>> (std::istream &is, UanPdp &pdp);
+  std::vector<Tap> m_taps;
+  Time m_resolution;
+
+};
+/**
+ * \brief Writes PDP to stream as list of arrivals
+ */
+std::ostream &operator<< (std::ostream &os, UanPdp &pdp);
+/**
+ * \brief Reads in list of arrivals from stream is
+ */
+std::istream &operator>> (std::ostream &is, UanPdp &pdp);
+
+/**
+ * \class UanPropModel
+ *
+ * Base class for implemented underwater propagation models
+ */
+class UanPropModel : public Object
+{
+public:
+  /**
+   * Computes pathloss between nodes a and b.
+   * \returns Pathloss in dB re 1 uPa
+   * \param a Ptr to mobility model of node a
+   * \param b Ptr to mobility model of node b
+   * \param txMode TX mode of transmission between a and b
+   */
+  virtual double GetPathLossDb (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode txMode) = 0;
+
+  /**
+   * \returns PDP for link between nodes a and b
+   * \param a Ptr to mobility model of node a
+   * \param b Ptr to mobility model of node b
+   * \param mode TX mode of transmission from a to b
+   */
+  virtual UanPdp GetPdp (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode) = 0;
+  /**
+   * Finds propagation delay between nodes a and b
+   * \param a Ptr to mobility model of node a
+   * \param b Ptr to mobility model of node b
+   * \param mode TX mode of transmission
+   * \returns Propagation delay
+   */
+  virtual Time GetDelay (Ptr<MobilityModel> a, Ptr<MobilityModel> b, UanTxMode mode) = 0;
+
+  /**
+   * Clears all pointer references
+   */
+  virtual void Clear (void);
+  
+  virtual void DoDispose (void);
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif /*UANPROPMODEL_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-transducer-hd.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,245 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "uan-transducer-hd.h"
+#include "ns3/simulator.h"
+#include "uan-prop-model.h"
+#include "uan-phy.h"
+#include "uan-channel.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("UanTransducerHd");
+
+namespace ns3 {
+namespace uan {
+
+NS_OBJECT_ENSURE_REGISTERED (UanTransducerHd);
+UanTransducerHd::UanTransducerHd ()
+  : UanTransducer (),
+    m_state (RX),
+    m_endTxTime (Seconds (0)),
+    m_cleared (false)
+{
+}
+
+UanTransducerHd::~UanTransducerHd ()
+{
+}
+
+void
+UanTransducerHd::Clear ()
+{
+  if (m_cleared)
+    {
+      return;
+    }
+  m_cleared = true;
+  if (m_channel)
+    {
+      m_channel->Clear ();
+      m_channel = 0;
+    }
+
+  UanPhyList::iterator it = m_phyList.begin ();
+  for (; it != m_phyList.end (); it++)
+    {
+      if (*it)
+        {
+          (*it)->Clear ();
+          *it = 0;
+        }
+    }
+  ArrivalList::iterator ait = m_arrivalList.begin ();
+  for (; ait != m_arrivalList.end (); ait++)
+    {
+      ait->GetPacket () = 0;
+    }
+  m_phyList.clear ();
+  m_arrivalList.clear ();
+  m_endTxEvent.Cancel ();
+}
+
+void
+UanTransducerHd::DoDispose ()
+{
+  Clear ();
+  UanTransducer::DoDispose ();
+}
+TypeId
+UanTransducerHd::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::UanTransducerHd")
+    .SetParent<Object> ()
+    .AddConstructor<UanTransducerHd> ()
+  ;
+  return tid;
+}
+
+UanTransducer::State
+UanTransducerHd::GetState () const
+{
+  return m_state;
+}
+
+
+bool
+UanTransducerHd::IsRx (void) const
+{
+  return m_state == RX;
+}
+
+bool
+UanTransducerHd::IsTx (void) const
+{
+  return m_state == TX;
+
+}
+
+const UanTransducer::ArrivalList &
+UanTransducerHd::GetArrivalList (void) const
+{
+  return m_arrivalList;
+}
+
+void
+UanTransducerHd::Receive (Ptr<Packet> packet,
+                          double rxPowerDb,
+                          UanTxMode txMode,
+                          UanPdp pdp)
+{
+  UanPacketArrival arrival (packet,
+                            rxPowerDb,
+                            txMode,
+                            pdp,
+                            Simulator::Now ());
+
+  m_arrivalList.push_back (arrival);
+  Time txDelay = Seconds (packet->GetSize () * 8.0 / txMode.GetDataRateBps ());
+  Simulator::Schedule (txDelay, &UanTransducerHd::RemoveArrival, this, arrival);
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Transducer in receive");
+  if (m_state == RX)
+    {
+      NS_LOG_DEBUG ("Transducer state = RX");
+      UanPhyList::const_iterator it = m_phyList.begin ();
+      for (; it != m_phyList.end (); it++)
+        {
+          NS_LOG_DEBUG ("Calling StartRx");
+          (*it)->StartRxPacket (packet, rxPowerDb, txMode, pdp);
+        }
+    }
+}
+
+void
+UanTransducerHd::Transmit (Ptr<UanPhy> src,
+                           Ptr<Packet> packet,
+                           double txPowerDb,
+                           UanTxMode txMode)
+{
+
+  Time endTxTime;
+  if (m_state == TX)
+    {
+      Simulator::Remove (m_endTxEvent);
+    }
+  else
+    {
+      m_state = TX;
+    }
+
+
+  Time delay = Seconds (packet->GetSize () * 8.0 / txMode.GetDataRateBps ());
+  NS_LOG_DEBUG ("Transducer transmitting:  TX delay = "
+                << delay << " seconds for packet size "
+                << packet->GetSize () << " bytes and rate = "
+                << txMode.GetDataRateBps () << " bps");
+  UanPhyList::const_iterator it = m_phyList.begin ();
+  for (; it != m_phyList.end (); it++)
+    {
+      if (src != (*it))
+        {
+          (*it)->NotifyTransStartTx (packet, txPowerDb, txMode);
+        }
+    }
+  m_channel->TxPacket (Ptr<UanTransducer> (this), packet, txPowerDb, txMode);
+
+
+  delay = std::max (delay, m_endTxTime - Simulator::Now ());
+
+  m_endTxEvent = Simulator::Schedule (delay, &UanTransducerHd::EndTx, this);
+  m_endTxTime = Simulator::Now () + delay;
+}
+
+void
+UanTransducerHd::EndTx (void)
+{
+  NS_ASSERT (m_state == TX);
+  m_state = RX;
+  m_endTxTime = Seconds (0);
+}
+void
+UanTransducerHd::SetChannel (Ptr<UanChannel> chan)
+{
+  NS_LOG_DEBUG ("Transducer setting channel");
+  m_channel = chan;
+
+}
+Ptr<UanChannel>
+UanTransducerHd::GetChannel (void) const
+{
+  return m_channel;
+}
+void
+UanTransducerHd::AddPhy (Ptr<UanPhy> phy)
+{
+  m_phyList.push_back (phy);
+}
+
+const UanTransducer::UanPhyList &
+UanTransducerHd::GetPhyList (void) const
+{
+  return m_phyList;
+}
+
+void
+UanTransducerHd::RemoveArrival (UanPacketArrival arrival)
+{
+
+  // Remove entry from arrival list
+  ArrivalList::iterator it = m_arrivalList.begin ();
+  for (; it != m_arrivalList.end (); it++)
+    {
+      if (it->GetPacket () == arrival.GetPacket ())
+        {
+          m_arrivalList.erase (it);
+          break;
+        }
+    }
+  UanPhyList::const_iterator ait = m_phyList.begin ();
+  for (; ait != m_phyList.end (); ait++)
+    {
+      (*ait)->NotifyIntChange ();
+    }
+
+}
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-transducer-hd.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,74 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANTRANSDUCERHD_H_
+#define UANTRANSDUCERHD_H_
+
+#include "uan-transducer.h"
+#include "ns3/simulator.h"
+namespace ns3 {
+namespace uan {
+
+/**
+ * \class UanTransducerHd
+ * \brief Half duplex implementation of transducer object
+ *
+ * This class will only allow attached Phy's to receive packets if not in TX mode
+ */
+class UanTransducerHd : public UanTransducer
+{
+public:
+  UanTransducerHd ();
+  virtual ~UanTransducerHd ();
+
+  static TypeId GetTypeId (void);
+
+  // inherited methods
+  virtual State GetState (void) const;
+  virtual bool IsRx (void) const;
+  virtual bool IsTx (void) const;
+  virtual const ArrivalList &GetArrivalList (void) const;
+  virtual void Receive (Ptr<Packet> packet, double rxPowerDb, UanTxMode txMode, UanPdp pdp);
+  virtual void Transmit (Ptr<UanPhy> src, Ptr<Packet> packet, double txPowerDb, UanTxMode txMode);
+  virtual void SetChannel (Ptr<UanChannel> chan);
+  virtual Ptr<UanChannel> GetChannel (void) const;
+  virtual void AddPhy (Ptr<UanPhy>);
+  virtual const UanPhyList &GetPhyList (void) const;
+  virtual void Clear (void);
+
+private:
+  State m_state;
+  ArrivalList m_arrivalList;
+  UanPhyList m_phyList;
+  Ptr<UanChannel> m_channel;
+  EventId m_endTxEvent;
+  Time m_endTxTime;
+  bool m_cleared;
+
+  void RemoveArrival (UanPacketArrival arrival);
+  void EndTx (void);
+protected:
+  virtual void DoDispose ();
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif /*UANTRANSDUCERSIMPLE_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-transducer.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,200 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+#ifndef UANTRANSDUCER_H_
+#define UANTRANSDUCER_H_
+
+#include "ns3/object.h"
+#include "ns3/packet.h"
+#include "uan-tx-mode.h"
+#include "uan-prop-model.h"
+
+#include <list>
+namespace ns3 {
+namespace uan {
+
+class UanPhy;
+class UanChannel;
+
+
+/**
+ * \class UanPacketArrival
+ *
+ * \brief Class consisting of packet arrival information (Time, RxPower, mode, PDP)
+ */
+class UanPacketArrival
+{
+public:
+
+  /* default constructor so python scan works */
+  UanPacketArrival ()
+  {
+  }
+
+  /**
+   * \param packet Packet arriving
+   * \param rxPowerDb RX signal power in dB of arriving packet
+   * \param txMode TX mode of arriving packet
+   * \param pdp Power delay profile of arriving packet
+   * \param arrTime Arrival time of packet
+   */
+  UanPacketArrival (Ptr<Packet> packet, double rxPowerDb, UanTxMode txMode, UanPdp pdp, Time arrTime)
+    : m_packet (packet),
+      m_rxPowerDb (rxPowerDb),
+      m_txMode (txMode),
+      m_pdp (pdp),
+      m_arrTime (arrTime)
+  {
+  }
+
+  ~UanPacketArrival()
+  {
+    m_packet = 0;
+  }
+
+  /**
+   * \returns Pointer to packet that arrived
+   */
+  inline Ptr<Packet> GetPacket (void) const
+  {
+    return m_packet;
+  }
+  /**
+   * \returns Received signal strength in dB re 1uPa
+   */
+  inline double GetRxPowerDb (void) const
+  {
+    return m_rxPowerDb;
+  }
+  /**
+   * \returns UanTxMode used to transmit packet
+   */
+  inline const UanTxMode &GetTxMode (void) const
+  {
+    return m_txMode;
+  }
+  /**
+   * \returns Arrival time of packet
+   */
+  inline Time GetArrivalTime (void) const
+  {
+    return m_arrTime;
+  }
+  /**
+   * \returns PDP of arriving signal
+   */
+  inline UanPdp GetPdp (void) const
+  {
+    return m_pdp;
+  }
+private:
+  Ptr<Packet> m_packet;
+  double m_rxPowerDb;
+  UanTxMode m_txMode;
+  UanPdp m_pdp;
+  Time m_arrTime;
+};
+
+/**
+ * \class UanTransducer
+ * \brief Virtual base for Transducer objects
+ *
+ * The Transducer was added to support classes such as UanPhyDual.
+ * In a generic Phy setting, this class functions to hold information about all
+ * possibly interfering packets.
+ */
+class UanTransducer : public Object
+{
+public:
+  /**
+   * \brief Transducer state (receiving or transmitting)
+   */
+  enum State {
+    TX, RX
+  };
+
+  /**
+   * \brief Arrival list is a standard template library list of UanPacketArrivals objects
+   */
+  typedef std::list<UanPacketArrival> ArrivalList;
+  /**
+   * \brief UanPhyList is a standard template library list of UanPhy objects
+   */
+  typedef std::list<Ptr<UanPhy> > UanPhyList;
+
+  /**
+   * \returns State (TX or RX) of this transducer
+   */
+  virtual State GetState (void) const = 0;
+
+  /**
+   * \returns True if this transducer is available for receiving an incoming packet.
+   */
+  virtual bool IsRx (void) const = 0;
+  /**
+   * \returns True if there is a packet being transmitted from this transducer.
+   */
+  virtual bool IsTx (void) const = 0;
+  /**
+   * \returns List of all packets currently crossing this node in the water.
+   */
+  virtual const ArrivalList &GetArrivalList (void) const = 0;
+  /**
+   * \brief Receive Notify this object that a new packet has arrived at this nodes location
+   * \param packet Packet arriving
+   * \param rxPowerDb Signal power in dB of arriving packet
+   * \param txMode Mode arriving packet is using
+   * \param pdp PDP of arriving signal
+   */
+  virtual void Receive (Ptr<Packet> packet, double rxPowerDb, UanTxMode txMode, UanPdp pdp) = 0;
+  /**
+   * \brief Transmit a packet from this transducer
+   * \param src Source PHY
+   * \param packet Packet to transmit
+   * \param txPowerDb Outgoing Tx power of packet
+   * \param txMode Mode to transmit packet with.
+   */
+  virtual void Transmit (Ptr<UanPhy> src, Ptr<Packet> packet, double txPowerDb, UanTxMode txMode) = 0;
+  /**
+   * \param chan Channel this transducer is attached to
+   */
+  virtual void SetChannel (Ptr<UanChannel> chan) = 0;
+  /**
+   * \returns Channel this transducer is attached to
+   */
+  virtual Ptr<UanChannel> GetChannel (void) const = 0;
+  /**
+   * \param phy Add phy above this transducer (may connect > 1 Phy to a transducer)
+   */
+  virtual void AddPhy (Ptr<UanPhy> phy) = 0;
+  /**
+   * \returns List of all Phy's this transducer sends packets to.
+   */
+  virtual const UanPhyList &GetPhyList (void) const = 0;
+  /**
+   * Clears all pointer references
+   */
+  virtual void Clear (void) = 0;
+
+};
+
+} // namespace uan
+} // namespace ns3
+
+#endif /*UANTRANSDUCER_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-tx-mode.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,307 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+#include "uan-tx-mode.h"
+#include "ns3/log.h"
+#include <map>
+#include <utility>
+
+NS_LOG_COMPONENT_DEFINE ("UanTxMode");
+
+namespace ns3 {
+namespace uan {
+
+UanTxMode::UanTxMode ()
+{
+}
+
+UanTxMode::~UanTxMode ()
+{
+}
+
+
+UanTxMode::ModulationType
+UanTxMode::GetModType (void) const
+{
+  return UanTxModeFactory::GetFactory ().GetModeItem (m_uid).m_type;
+}
+
+uint32_t
+UanTxMode::GetDataRateBps (void) const
+{
+  return UanTxModeFactory::GetFactory ().GetModeItem (m_uid).m_dataRateBps;
+}
+
+uint32_t
+UanTxMode::GetPhyRateSps (void) const
+{
+  return UanTxModeFactory::GetFactory ().GetModeItem (m_uid).m_phyRateSps;
+}
+
+uint32_t
+UanTxMode::GetCenterFreqHz (void) const
+{
+  return UanTxModeFactory::GetFactory ().GetModeItem (m_uid).m_cfHz;
+}
+
+uint32_t
+UanTxMode::GetBandwidthHz (void) const
+{
+  return UanTxModeFactory::GetFactory ().GetModeItem (m_uid).m_bwHz;
+}
+
+uint32_t
+UanTxMode::GetConstellationSize (void) const
+{
+  return UanTxModeFactory::GetFactory ().GetModeItem (m_uid).m_constSize;
+}
+
+std::string
+UanTxMode::GetName (void) const
+{
+  return UanTxModeFactory::GetFactory ().GetModeItem (m_uid).m_name;
+}
+
+uint32_t 
+UanTxMode::GetUid (void) const
+{
+  return m_uid;
+}
+
+std::ostream &
+operator<< (std::ostream & os, const UanTxMode &mode)
+{
+  os << mode.m_uid;
+  return os;
+}
+
+std::istream &
+operator>> (std::istream & is, UanTxMode &mode)
+{
+  std::string name;
+  uint32_t duh;
+
+  is >> duh;
+
+  mode.m_uid = duh;
+  return is;
+}
+
+
+
+UanTxModeFactory::UanTxModeFactory ()
+  : m_nextUid (0)
+{
+
+}
+UanTxModeFactory::~UanTxModeFactory ()
+{
+  m_modes.clear ();
+}
+bool
+UanTxModeFactory::NameUsed (std::string name)
+{
+  std::map<uint32_t, UanTxModeItem>::iterator it = m_modes.begin ();
+
+  for (; it != m_modes.end (); it++)
+    {
+      if ((*it).second.m_name == name)
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
+UanTxMode
+UanTxModeFactory::CreateMode (UanTxMode::ModulationType type,
+                              uint32_t dataRateBps,
+                              uint32_t phyRateSps,
+                              uint32_t cfHz,
+                              uint32_t bwHz,
+                              uint32_t constSize,
+                              std::string name)
+{
+  UanTxModeFactory &factory = UanTxModeFactory::GetFactory ();
+
+
+  UanTxModeItem *item;
+
+  if (factory.NameUsed (name))
+    {
+      NS_LOG_WARN ("Redefining UanTxMode with name \"" << name << "\"");
+      item = &factory.GetModeItem (name);
+    }
+  else
+    {
+      item = &factory.m_modes[factory.m_nextUid];
+      item->m_uid = factory.m_nextUid++;
+    }
+
+  item->m_type = type;
+  item->m_dataRateBps = dataRateBps;
+  item->m_phyRateSps = phyRateSps;
+  item->m_cfHz = cfHz;
+  item->m_bwHz = bwHz;
+  item->m_constSize = constSize;
+  item->m_name = name;
+  return factory.MakeModeFromItem (*item);
+}
+
+UanTxModeFactory::UanTxModeItem &
+UanTxModeFactory::GetModeItem (uint32_t uid)
+{
+  if (uid >= m_nextUid)
+    {
+      NS_FATAL_ERROR ("Attempting to retrieve UanTxMode with uid, "
+                      << uid << ", >= m_nextUid");
+    }
+
+  return m_modes[uid];
+}
+
+UanTxModeFactory::UanTxModeItem &
+UanTxModeFactory::GetModeItem (std::string name)
+{
+  std::map<uint32_t, UanTxModeItem>::iterator it = m_modes.begin ();
+  for (; it != m_modes.end (); it++)
+    {
+      if ((*it).second.m_name == name)
+        {
+          return (*it).second;
+        }
+    }
+  NS_FATAL_ERROR ("Unknown mode, \"" << name << "\", requested from mode factory");
+  return (*it).second;  // dummy to get rid of warning
+}
+
+UanTxMode
+UanTxModeFactory::GetMode (std::string name)
+{
+  UanTxModeFactory &factory = UanTxModeFactory::GetFactory ();
+  return factory.MakeModeFromItem (factory.GetModeItem (name));
+}
+
+UanTxMode
+UanTxModeFactory::GetMode (uint32_t uid)
+{
+  UanTxModeFactory &factory = UanTxModeFactory::GetFactory ();
+  return factory.MakeModeFromItem (factory.GetModeItem (uid));
+}
+
+UanTxMode
+UanTxModeFactory::MakeModeFromItem (const UanTxModeItem &item)
+{
+  UanTxMode mode;
+  mode.m_uid = item.m_uid;
+  return mode;
+}
+
+UanTxModeFactory &
+UanTxModeFactory::GetFactory (void)
+{
+  static UanTxModeFactory factory;
+  return factory;
+}
+
+UanModesList::UanModesList (void)
+{
+}
+
+UanModesList::~UanModesList (void)
+{
+  m_modes.clear ();
+}
+
+void
+UanModesList::AppendMode (UanTxMode newMode)
+{
+  m_modes.push_back (newMode);
+}
+
+void
+UanModesList::DeleteMode (uint32_t modeNum)
+{
+  NS_ASSERT (modeNum < m_modes.size ());
+
+
+  std::vector<UanTxMode>::iterator it = m_modes.begin ();
+  for (uint32_t i = 0; i < modeNum; i++)
+    {
+      it++;
+    }
+  it = m_modes.erase (it);
+}
+
+UanTxMode
+UanModesList::operator[] (uint32_t i) const
+{
+  NS_ASSERT (i < m_modes.size ());
+  return m_modes[i];
+}
+
+uint32_t
+UanModesList::GetNModes (void) const
+{
+  return m_modes.size ();
+}
+
+std::ostream &
+operator << (std::ostream &os, const UanModesList &ml)
+{
+
+  os << ml.GetNModes () << "|";
+
+  for (uint32_t i = 0; i < ml.m_modes.size (); i++)
+    {
+      os << ml[i] << "|";
+    }
+  return os;
+}
+std::istream &
+operator >> (std::istream &is, UanModesList &ml)
+{
+  char c;
+
+  int numModes;
+
+  is >> numModes >> c;
+  if (c != '|')
+    {
+      is.setstate (std::ios_base::failbit);
+    }
+  ml.m_modes.clear ();
+  ml.m_modes.resize (numModes);
+
+  for (int i = 0; i < numModes; i++)
+    {
+      is >> ml.m_modes[i] >> c;
+      if (c != '|')
+        {
+          is.setstate (std::ios_base::failbit);
+        }
+    }
+
+  return is;
+}
+
+ATTRIBUTE_HELPER_CPP (UanModesList);
+
+} // namespace uan
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/model/uan-tx-mode.h	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,210 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#ifndef UANTXMODE_H
+#define UANTXMODE_H
+
+#include "ns3/object.h"
+#include <map>
+
+namespace ns3 {
+namespace uan {
+
+class UanTxModeFactory;
+class UanTxMode;
+
+/**
+ * \class UanTxMode
+ * \brief Abstraction of packet modulation information
+ */
+class UanTxMode
+{
+public:
+  UanTxMode ();
+  ~UanTxMode ();
+
+  /**
+   * Modulation type
+   */
+  typedef enum {
+    PSK, QAM, FSK, OTHER
+  } ModulationType;
+  /**
+   * \returns The modulation type of the mode
+   */
+  ModulationType GetModType (void) const;
+  /**
+   * \returns Data rate of the TX mode in bits per second
+   */
+  uint32_t GetDataRateBps (void) const;
+  /**
+   * \returns PHY rate in symbols per second
+   */
+  uint32_t GetPhyRateSps (void) const;
+  /**
+   * \returns Center frequency of transmitted signal in Hz
+   */
+  uint32_t GetCenterFreqHz (void) const;
+  /**
+   * \returns Bandwidth of transmitted signal in Hz
+   */
+  uint32_t GetBandwidthHz (void) const;
+  /**
+   * \returns Number of constellation points in modulation
+   */
+  uint32_t GetConstellationSize (void) const;
+  /**
+   * \returns Name
+   */
+  std::string GetName (void) const;
+  /**
+   * \returns Unique ID
+   */
+  uint32_t GetUid (void) const;
+
+private:
+  friend class UanTxModeFactory;
+  friend std::ostream &operator<< (std::ostream & os, const UanTxMode &mode);
+  friend std::istream &operator>> (std::istream & is, UanTxMode &mode);
+
+
+  uint32_t m_uid;
+
+};
+/**
+ * \brief Writes tx mode entry to stream os
+ */
+std::ostream & operator << (std::ostream & os, const UanTxMode &mode);
+/**
+ * \brief Reads tx mode entry from stream is
+ */
+std::istream & operator >> (std::istream & is, const UanTxMode &mode);
+
+class UanTxModeFactory
+{
+public:
+  UanTxModeFactory ();
+  ~UanTxModeFactory ();
+
+  /**
+   *
+   * \param type modulation type
+   * \param dataRateBps Data rate in BPS
+   * \param phyRateSps  Symbol rate in symbols per second
+   * \param cfHz Center frequency in Hz
+   * \param bwHz Bandwidth in Hz
+   * \param constSize Modulation constellation size (2 for BPSK, 4 for QPSK)
+   * \param name Unique string name for this transmission mode
+   */
+  static UanTxMode CreateMode (UanTxMode::ModulationType type,
+                               uint32_t dataRateBps,
+                               uint32_t phyRateSps,
+                               uint32_t cfHz,
+                               uint32_t bwHz,
+                               uint32_t constSize,
+                               std::string name);
+
+  /**
+   * \param name String name of mode
+   * \returns Mode with given name
+   */
+  static UanTxMode GetMode (std::string name);
+  /**
+   * \param uid Unique ID of mode
+   * \returns The mode with given uid
+   */
+  static UanTxMode GetMode (uint32_t uid);
+private:
+  friend class UanTxMode;
+  uint32_t m_nextUid;
+
+  struct UanTxModeItem
+  {
+    UanTxMode::ModulationType m_type;
+    uint32_t m_cfHz;
+    uint32_t m_bwHz;
+    uint32_t m_dataRateBps;
+    uint32_t m_phyRateSps;
+    uint32_t m_constSize;
+    uint32_t m_uid;
+    std::string m_name;
+  };
+
+  std::map<uint32_t, UanTxModeItem> m_modes;
+  bool NameUsed (std::string name);
+  static UanTxModeFactory &GetFactory (void);
+  UanTxModeItem &GetModeItem (uint32_t uid);
+  UanTxModeItem &GetModeItem (std::string name);
+  UanTxMode MakeModeFromItem (const UanTxModeItem &item);
+
+};
+
+/**
+ * \class UanModesList
+ * \brief Container for UanTxModes
+ */
+class UanModesList 
+{
+public:
+  UanModesList ();
+  virtual ~UanModesList ();
+
+  /**
+   * \param mode Add mode to list
+   */
+  void AppendMode (UanTxMode mode);
+  /**
+   * \brief delete mode at given index
+   * \param num Index of mode to delete
+   */
+  void DeleteMode (uint32_t num);
+  /**
+   * \param index Mode index
+   * \returns mode at given index
+   */
+  UanTxMode operator[] (uint32_t index) const;
+  /**
+   * \returns Number of modes in list
+   */
+  uint32_t GetNModes (void) const;
+
+
+private:
+  std::vector<UanTxMode> m_modes;
+  friend std::ostream &operator << (std::ostream &os, const UanModesList &ml);
+  friend std::istream &operator >> (std::istream &is, UanModesList &ml);
+};
+
+/**
+ * \brief Write UanModesList to stream os
+ */
+std::ostream &operator << (std::ostream &os, const UanModesList &ml);
+/**
+ * \brief Read UanModesList from stream is
+ */
+std::istream &operator >> (std::istream &is, UanModesList &ml);
+
+///UanModesList is attribute value
+ATTRIBUTE_HELPER_HEADER (UanModesList);
+
+} // namespace uan
+} // namespace ns3
+
+#endif // UANTXMODE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/test/uan-test.cc	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,269 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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: Leonard Tracy <lentracy@gmail.com>
+ */
+
+#include "ns3/uan-net-device.h"
+#include "ns3/uan-channel.h"
+#include "ns3/uan-mac-aloha.h"
+#include "ns3/uan-phy-gen.h"
+#include "ns3/uan-transducer-hd.h"
+#include "ns3/uan-prop-model-ideal.h"
+#include "ns3/constant-position-mobility-model.h"
+#include "ns3/simulator.h"
+#include "ns3/test.h"
+#include "ns3/node.h"
+#include "ns3/object-factory.h"
+#include "ns3/pointer.h"
+#include "ns3/callback.h"
+
+using namespace ns3;
+
+class UanTest : public TestCase
+{
+public:
+  UanTest ();
+
+  virtual bool DoRun (void);
+private:
+  Ptr<UanNetDevice> CreateNode (Vector pos, Ptr<UanChannel> chan);
+  bool DoPhyTests ();
+  uint32_t DoOnePhyTest (Time t1, Time t2, uint32_t r1, uint32_t r2, Ptr<UanPropModel> prop, uint32_t mode1 = 0, uint32_t mode2 = 0);
+  bool RxPacket (Ptr<NetDevice> dev, Ptr<const Packet> pkt, uint16_t mode, const Address &sender);
+  void SendOnePacket (Ptr<UanNetDevice> dev, uint32_t mode);
+  ObjectFactory m_phyFac;
+  uint32_t m_bytesRx;
+
+};
+
+
+UanTest::UanTest () : TestCase ("UAN")
+{
+
+}
+
+bool
+UanTest::RxPacket (Ptr<NetDevice> dev, Ptr<const Packet> pkt, uint16_t mode, const Address &sender)
+{
+  m_bytesRx += pkt->GetSize ();
+  return true;
+}
+void
+UanTest::SendOnePacket (Ptr<UanNetDevice> dev, uint32_t mode)
+{
+  Ptr<Packet> pkt = Create<Packet> (17);
+  dev->Send (pkt, dev->GetBroadcast (), mode);
+
+}
+Ptr<UanNetDevice>
+UanTest::CreateNode (Vector pos, Ptr<UanChannel> chan)
+{
+
+
+  Ptr<UanPhy> phy = m_phyFac.Create<UanPhy> ();
+  Ptr<Node> node = CreateObject<Node> ();
+  Ptr<UanNetDevice> dev = CreateObject<UanNetDevice> ();
+  Ptr<UanMacAloha> mac = CreateObject<UanMacAloha> ();
+  Ptr<ConstantPositionMobilityModel> mobility = CreateObject<ConstantPositionMobilityModel> ();
+
+  Ptr<UanTransducerHd> trans = CreateObject<UanTransducerHd> ();
+
+  mobility->SetPosition (pos);
+  node->AggregateObject (mobility);
+  mac->SetAddress (UanAddress::Allocate ());
+
+  dev->SetPhy (phy);
+  dev->SetMac (mac);
+  dev->SetChannel (chan);
+  dev->SetTransducer (trans);
+  node->AddDevice (dev);
+
+  return dev;
+}
+
+
+uint32_t
+UanTest::DoOnePhyTest (Time txTime1,
+                       Time txTime2,
+                       uint32_t r1,
+                       uint32_t r2,
+                       Ptr<UanPropModel> prop,
+                       uint32_t mode1,
+                       uint32_t mode2)
+{
+
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  channel->SetAttribute ("PropagationModel", PointerValue (prop));
+
+  Ptr<UanNetDevice> dev0 = CreateNode (Vector (r1,50,50), channel);
+  Ptr<UanNetDevice> dev1 = CreateNode (Vector (0,50,50), channel);
+  Ptr<UanNetDevice> dev2 = CreateNode (Vector (r1 + r2, 50, 50), channel);
+
+  dev0->SetReceiveCallback (MakeCallback (&UanTest::RxPacket, this));
+
+  Simulator::Schedule (txTime1, &UanTest::SendOnePacket, this, dev1, mode1);
+  Simulator::Schedule (txTime2, &UanTest::SendOnePacket, this, dev2, mode2);
+
+  m_bytesRx = 0;
+  Simulator::Stop (Seconds (20.0));
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  return m_bytesRx;
+}
+
+
+bool
+UanTest::DoPhyTests ()
+{
+  // Phy Gen / Default PER / Default SINR
+  AttributeList phyList;
+  UanModesList mList;
+  UanTxMode mode = UanTxModeFactory::CreateMode (UanTxMode::FSK, 80, 80, 10000, 4000, 2, "TestMode");
+  mList.AppendMode (UanTxMode (mode));
+  Ptr<UanPhyPerGenDefault> perDef = CreateObject<UanPhyPerGenDefault> ();
+  Ptr<UanPhyCalcSinrDefault> sinrDef = CreateObject<UanPhyCalcSinrDefault> ();
+  TypeId phyId = TypeId::LookupByName ("ns3::UanPhyGen");
+  m_phyFac.SetTypeId (phyId);
+  phyList.SetWithTid (phyId, "PerModel", PointerValue (perDef));
+  phyList.SetWithTid (phyId, "SinrModel", PointerValue (sinrDef));
+  phyList.SetWithTid (phyId, "SupportedModes", UanModesListValue (mList));
+
+  m_phyFac.Set (phyList);
+
+  Ptr<UanPropModelIdeal> prop = CreateObject<UanPropModelIdeal> ();
+
+  // No collision (Get 2 packets)
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (3.001), 50, 50, prop),
+                         34, "Should have received 34 bytes from 2 disjoint packets");
+
+  // Collision (Lose both packets)
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (2.99), 50, 50, prop),
+                         0, "Expected collision resulting in loss of both packets");
+
+
+  // Phy Gen / FH-FSK SINR check
+
+  Ptr<UanPhyCalcSinrFhFsk> sinrFhfsk = CreateObject <UanPhyCalcSinrFhFsk> ();
+  phyList.Reset ();
+  phyList.SetWithTid (phyId, "PerModel", PointerValue (perDef));
+  phyList.SetWithTid (phyId, "SinrModel", PointerValue (sinrFhfsk));
+  phyList.SetWithTid (phyId, "SupportedModes", UanModesListValue (mList));
+  m_phyFac.Set (phyList);
+
+#ifdef UAN_PROP_BH_INSTALLED
+  Ptr<UanPropModelBh> prop = CreateObject<UanPropModelBh> ();
+#endif // UAN_PROP_BH_INSTALLED
+
+  //  No collision (Get 2 packets)
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (3.001), 50, 50, prop),
+                         34, "Should have received 34 bytes from 2 disjoint packets");
+
+  // Should correctly receive first arriving packet
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (1.0126), 50, 50, prop),
+                         17, "Should have recieved 17 bytes from first arriving packet");
+
+  // Packets should collide and both be lost
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (1.0 + 7.01 * (13.0 / 80.0)), 50, 50, prop),
+                         0, "Packets should collide, but received data");
+
+  // Phy Dual
+  UanTxMode mode00 = UanTxModeFactory::CreateMode (UanTxMode::FSK, 80, 80, 10000, 4000, 2, "TestMode00");
+  UanTxMode mode10 = UanTxModeFactory::CreateMode (UanTxMode::FSK, 80, 80, 11000, 4000, 2, "TestMode10");
+  UanTxMode mode20 = UanTxModeFactory::CreateMode (UanTxMode::FSK, 80, 80, 15000, 4000, 2, "TestMode20");
+  UanTxMode mode01 = UanTxModeFactory::CreateMode (UanTxMode::FSK, 80, 80, 10000, 4000, 2, "TestMode01");
+  UanTxMode mode11 = UanTxModeFactory::CreateMode (UanTxMode::FSK, 80, 80, 11000, 4000, 2, "TestMode11");
+  UanTxMode mode21 = UanTxModeFactory::CreateMode (UanTxMode::FSK, 80, 80, 15000, 4000, 2, "TestMode21");
+
+  UanModesList m0;
+  m0.AppendMode (mode00);
+  m0.AppendMode (mode10);
+  m0.AppendMode (mode20);
+  UanModesList m1;
+  m1.AppendMode (mode01);
+  m1.AppendMode (mode11);
+  m1.AppendMode (mode21);
+
+  phyId = TypeId::LookupByName ("ns3::UanPhyDual");
+  m_phyFac.SetTypeId (phyId);
+  phyList.Reset ();
+  phyList.SetWithTid (phyId, "SupportedModesPhy1", UanModesListValue (m0));
+  phyList.SetWithTid (phyId, "SupportedModesPhy2", UanModesListValue (m1));
+  m_phyFac.Set (phyList);
+
+  // No collision (Get 2 packets)
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (3.01), 50, 50, prop),
+                         34, "Expected no collision");
+
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (2.99), 50, 50, prop, 0, 0),
+                         0, "Expected collision with both packets lost");
+
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (2.99), 50, 50, prop, 0, 2),
+                         17, "Expected collision with only one packets lost");
+
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (2.99), 50, 50, prop, 0, 5),
+                         34, "Expected no collision");
+
+  NS_TEST_ASSERT_MSG_EQ (DoOnePhyTest (Seconds (1.0), Seconds (2.99), 50, 50, prop, 2, 3),
+                         34, "Expected no collision");
+
+  return false;
+}
+
+bool
+UanTest::DoRun (void)
+{
+
+  Ptr<UanPhyPerUmodem> per = CreateObject<UanPhyPerUmodem> ();
+  Ptr<Packet> pkt = Create<Packet> (1000);
+  double error = per->CalcPer (pkt, 9, UanPhyGen::GetDefaultModes ()[0]);
+  NS_TEST_ASSERT_MSG_EQ_TOL (error, 0.539, 0.001, "Got PER outside of tolerance");
+
+#ifdef UAN_PROP_BH_INSTALLED
+  //  Correct DB lookup for BH prop.
+  Ptr<UanPropModelBh> propBh = CreateObject<UanPropModelBh> ();
+  BellhopResp resp = propBh->GetResp (10000, 50, 50, 1000);
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (resp.GetPathLossDb (), -44.1753, 0.001, "Got BH Pathloss outside of tolerance");
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (resp.GetPdp ().GetTap (4).GetAmp (), 0.14159, 0.001, "Got BH arrival outside of tolerance");
+
+#endif // UAN_PROP_BH_INSTALLED
+
+  return DoPhyTests ();
+
+}
+
+
+class UanTestSuite : public TestSuite
+{
+public:
+  UanTestSuite ();
+};
+
+UanTestSuite::UanTestSuite ()
+  :  TestSuite ("devices-uan", UNIT)
+{
+  AddTestCase (new UanTest);
+}
+
+UanTestSuite g_uanTestSuite;
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packages/uan/wscript	Tue Oct 26 08:41:33 2010 -0700
@@ -0,0 +1,56 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    module = bld.create_ns3_module('uan', ['node'])
+    module.source = [
+        'model/uan-channel.cc',
+        'model/uan-phy-gen.cc',
+        'model/uan-transducer-hd.cc',
+        'model/uan-address.cc',
+	      'model/uan-net-device.cc',
+        'model/uan-tx-mode.cc',
+        'model/uan-prop-model.cc',
+        'model/uan-prop-model-ideal.cc',
+        'model/uan-mac-aloha.cc',
+        'model/uan-header-common.cc',
+        'model/uan-noise-model-default.cc',
+        'model/uan-mac-cw.cc',
+        'model/uan-prop-model-thorp.cc',
+        'model/uan-phy-dual.cc',
+        'model/uan-header-rc.cc',
+        'model/uan-mac-rc.cc',
+        'model/uan-mac-rc-gw.cc',
+        'model/uan-phy.cc',
+        'model/uan-noise-model.cc',
+        'helper/uan-helper.cc',
+        'test/uan-test.cc',
+        ]
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'uan'
+    headers.source = [
+        'model/uan-channel.h',
+        'model/uan-phy.h',
+        'model/uan-mac.h',
+	      'model/uan-net-device.h',
+	      'model/uan-prop-model.h',
+	      'model/uan-tx-mode.h',
+	      'model/uan-transducer.h',
+        'model/uan-phy-gen.h',
+	      'model/uan-transducer-hd.h',
+        'model/uan-address.h',
+        'model/uan-prop-model-ideal.h',
+        'model/uan-mac-aloha.h',
+        'model/uan-header-common.h',
+        'model/uan-noise-model.h',
+        'model/uan-noise-model-default.h',
+        'model/uan-mac-cw.h',
+        'model/uan-prop-model-thorp.h',
+        'model/uan-phy-dual.h',
+        'model/uan-header-rc.h',
+        'model/uan-mac-rc.h',
+        'helper/uan-helper.h',
+        'model/uan-mac-rc-gw.h',
+        ]
+
+    if (bld.env['ENABLE_EXAMPLES']):
+      bld.add_subdirs('examples')