Index: src/rns/model/rns-specialization.cc |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/rns/model/rns-specialization.cc |
@@ -0,0 +1,488 @@ |
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
+/* |
+ * Copyright (c) 2012 Michal Paszta |
+ * |
+ * 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: Michal Paszta |
+ */ |
+#include <ns3/rns-helper.h> |
+#include "rns.h" |
+#include "rns-header.h" |
+#include "ns3/wifi-net-device.h" |
+#include "ns3/yans-wifi-channel.h" |
+#include "ns3/pointer.h" |
+#include "ns3/integer.h" |
+#include "ns3/double.h" |
+ |
+namespace ns3 { |
+namespace rns { |
+ |
+ |
+/* Ipv4 specialization */ |
+ |
+template <> TypeId Rns<Ipv4Address>::GetTypeId(void) |
+{ |
+ static TypeId tid = TypeId ("ns3::rns::RnsIpv4AddressImpl") |
+ .SetParent<Object> () |
+ .AddConstructor<Rns<Ipv4Address> > () |
+ .AddAttribute("Test","Set to true for testing.", |
+ BooleanValue(false), |
+ MakeBooleanAccessor(&Rns<Ipv4Address>::IsTest), |
+ MakeBooleanChecker()) |
+ .AddAttribute("ConnectivityMaintenanceMode","Use automatic radio range estimation and maintain network's connectivity.", |
+ BooleanValue(false), |
+ MakeBooleanAccessor(&Rns<Ipv4Address>::ConnectivityMaintenanceMode), |
+ MakeBooleanChecker()) |
+ .AddAttribute("EventTriggerredBroadcast","Whether Rns broadcast should be triggerred by events or by timer", |
+ BooleanValue(false), |
+ MakeBooleanAccessor(&Rns<Ipv4Address>::EventTrigerredBroadcast), |
+ MakeBooleanChecker()) |
+ .AddAttribute("UpdateInterval","Interval between automatic Rns updates; Rns message is sent only if EventTriggerBroadcast is set to false.", |
+ TimeValue(Seconds(1.0)), |
+ MakeTimeAccessor(&Rns<Ipv4Address>::UpdateInterval), |
+ MakeTimeChecker()) |
+ .AddAttribute("MaxEntryAge","The age at which a node's position, range and status are regarded out of date.", |
+ TimeValue(Seconds(100)), |
+ MakeTimeAccessor(&Rns<Ipv4Address>::MaxEntryAge), |
+ MakeTimeChecker()) |
+ .AddAttribute("UpdateIntervalTimeScatter","Time scatter of Update Interval to avoid collision [ms].", |
+ DoubleValue(100), |
+ MakeDoubleAccessor(&Rns<Ipv4Address>::UpdateIntervalTimeScatter), |
+ MakeDoubleChecker<double>()) |
+ .AddAttribute("AllowedStatusChanges","How often is the status allowed to change per update period.", |
+ IntegerValue(5), |
+ MakeIntegerAccessor(&Rns<Ipv4Address>::AllowedStatusChanges), |
+ MakeIntegerChecker<uint32_t>()) |
+ .AddAttribute ("RangeEstimationAccuracy","How accurate should the range estimation be [m].", |
+ DoubleValue (0.01), |
+ MakeDoubleAccessor (&Rns<Ipv4Address>::RangeEstimationAccuracy), |
+ MakeDoubleChecker<double> ()) |
+ .AddAttribute ("ProtocolPeriodicUpdate","Whether the protocol will provide a periodic update on neighbors situation.", |
+ BooleanValue(false), |
+ MakeBooleanAccessor(&Rns<Ipv4Address>::ProtocolPeriodicUpdate), |
+ MakeBooleanChecker()) |
+ .AddAttribute ("PositionInRnsHeader","Whether position information has to be passed in RNS header.", |
+ BooleanValue(true), |
+ MakeBooleanAccessor(&Rns<Ipv4Address>::PositionInRnsHeader), |
+ MakeBooleanChecker()) |
+ ; |
+ return tid; |
+} |
+ |
+template <> |
+void Rns<Ipv4Address>::Ipv4Receive (Ptr<Socket> socket) |
+{ |
+ while (m_socket->GetRxAvailable () > 0) |
+ { |
+ Address from; |
+ Ptr<Packet> p = m_socket->RecvFrom (0xffffffff, 0, from); |
+ Ipv4Header ipv4; |
+ p->RemoveHeader (ipv4); |
+ Ipv4Address sender = ipv4.GetSource(); |
+ |
+ RnsHeader<Ipv4Address> rnsMsg; |
+ if (PositionInRnsHeader) rnsMsg.SetPositionInRnsHeader(true); |
+ p->RemoveHeader (rnsMsg); |
+ ReceiveRnsMessage(rnsMsg,sender); |
+ } |
+} |
+ |
+template <> |
+void Rns<Ipv4Address>::Ipv4Send (RnsHeader<Ipv4Address> h) |
+{ |
+ Ptr<Packet> p = Create<Packet>(); |
+ p->AddHeader(h); |
+ |
+ //Set power level. |
+ uint8_t txPowerLevelBuffer = m_yansWifiPhy->GetTxPowerLevel(); |
+ m_yansWifiPhy->SetTxPowerLevel(m_broadcastPowerLevel); |
+ |
+ Ipv4Address destination = Ipv4Address ("255.255.255.255"); |
+ m_socket->SendTo(p,0,InetSocketAddress(destination)); |
+ |
+ //Reset original power level. |
+ m_yansWifiPhy->SetTxPowerLevel(txPowerLevelBuffer); |
+} |
+ |
+template <> |
+void Rns<Ipv4Address>::Start(Ptr<Node> node) |
+{ |
+ if (IsTest) |
+ { |
+ PositionInRnsHeader = false; |
+ m_protocolUpdate = MakeNullCallback<void, Neighbor<Ipv4Address> > (); |
+ return; |
+ } |
+ m_node = node; |
+ m_redundantRelatedNodes.clear(); |
+ |
+ m_broadcastTimer.SetFunction(&Rns<Ipv4Address>::UpdateTimerExpire,this); |
+ m_broadcastTimer.Schedule(UpdateInterval |
+ - Time (MilliSeconds (UniformVariable().GetValue(0.0, UpdateIntervalTimeScatter)))); |
+ |
+ m_agingTimer.SetFunction(&Rns<Ipv4Address>::AgingTimerExpire,this); |
+ m_agingTimer.Schedule(Seconds (1)); |
+ m_neighbors.SetMaxAge(MaxEntryAge); |
+ |
+ Ptr<NetDevice> netDev = m_node->GetDevice(0); |
+ Ptr<WifiNetDevice> wifiNetDev = DynamicCast<WifiNetDevice>(netDev); |
+ |
+ //Phy detection |
+ Ptr<WifiPhy> wifiPhy = wifiNetDev->GetPhy(); |
+ Ptr<YansWifiPhy> yansWifiPhy = DynamicCast<YansWifiPhy>(wifiPhy); |
+ if (yansWifiPhy != NULL) |
+ { |
+ m_yansWifiPhy = yansWifiPhy; |
+ } |
+ |
+ //Mobility Detection |
+ Ptr<MobilityModel> AggregatedMobilityModel = m_node->GetObject<MobilityModel>(); |
+ NS_ASSERT(AggregatedMobilityModel != NULL); |
+ this->SetMobility(AggregatedMobilityModel); |
+ |
+ //PropagationLossModel detection |
+ Ptr<Channel> wifiCh = wifiNetDev->GetChannel(); |
+ Ptr<YansWifiChannel> yansWifiCh = DynamicCast<YansWifiChannel>(wifiCh); |
+ PointerValue pval; |
+ wifiCh->GetAttribute("PropagationLossModel",pval); |
+ Ptr<PropagationLossModel> prop = pval.Get<PropagationLossModel> (); |
+ if (prop != NULL) |
+ { |
+ m_propagationModel = prop; |
+ } |
+ |
+ SetRanges(); |
+ RangeUpdate(); |
+ |
+ //Ipv4 stack detection |
+ Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> (); |
+ // The assertion should be altered or removed when other stacks are supported. |
+ NS_ASSERT_MSG(ipv4 != NULL, "No Ipv4 stack detected.\n"); |
+ if (ipv4 != NULL) |
+ { |
+ //Obtain this nodes own address. |
+ m_id = ipv4->GetAddress(1,0).GetLocal(); |
+ |
+ m_socket = Socket::CreateSocket (m_node, |
+ TypeId::LookupByName ("ns3::Ipv4RawSocketFactory")); |
+ NS_ASSERT_MSG (m_socket != 0,"Socket not created."); |
+ m_socket->SetAttribute ("Protocol", UintegerValue (4)); // ip |
+ m_socket->SetRecvCallback (MakeCallback (&Rns::Ipv4Receive, this)); |
+ InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0); |
+ int status; |
+ status = m_socket->Bind (src); |
+ NS_ASSERT (status != -1); |
+ m_socket->SetAllowBroadcast(true); |
+ |
+ return; |
+ } |
+} |
+ |
+template <> |
+uint32_t NeighborsTable<Ipv4Address>::Ipv4ToNodeNumber(Ipv4Address addr) const |
+{ |
+ uint32_t n = addr.Get(); |
+ n = n & 0x000000FF; |
+ return n-1; |
+} |
+ |
+template <> |
+uint32_t Neighbor<Ipv4Address>::Ipv4ToNodeNumber(Ipv4Address addr) const |
+{ |
+ uint32_t n = addr.Get(); |
+ n = n & 0x000000FF; |
+ return n-1; |
+} |
+ |
+template <> |
+uint32_t Rns<Ipv4Address>::Ipv4ToNodeNumber(Ipv4Address addr) const |
+{ |
+ uint32_t n = addr.Get(); |
+ n = n & 0x000000FF; |
+ return n-1; |
+} |
+ |
+template <> |
+TypeId RnsHeader<Ipv4Address>::GetTypeId (void) |
+{ |
+ static TypeId tid = TypeId ("ns3::rns::RnsHeaderIpv4Address") |
+ .SetParent<Header> () |
+ .AddConstructor<RnsHeader>(); |
+ return tid; |
+} |
+ |
+template <> |
+uint32_t RnsHeader<Ipv4Address>::GetSerializedSize () const |
+{ |
+ uint32_t size = 1 + sizeof(Ipv4Address) + 4; //status + id + range |
+ if (PositionInRnsHeader) |
+ { |
+ size += 8; // + position |
+ } |
+ size += sizeof(uint32_t); //entries_number |
+ size += m_entriesNumber*sizeof(Ipv4Address); |
+ return size; |
+} |
+ |
+template <> |
+void RnsHeader<Ipv4Address>::Serialize (Buffer::Iterator start) const |
+{ |
+ WriteTo (start,m_id); |
+ start.WriteU8(m_status); |
+ start.WriteHtonU32(m_range); |
+ if (PositionInRnsHeader) |
+ { |
+ start.WriteHtonU32(m_x); |
+ start.WriteHtonU32(m_y); |
+ } |
+ start.WriteHtonU32(m_entriesNumber); |
+ for (std::vector<Ipv4Address>::const_iterator i = m_rrns.begin(); |
+ i != m_rrns.end(); i++) |
+ { |
+ WriteTo(start,*i); |
+ } |
+} |
+ |
+template <> |
+uint32_t RnsHeader<Ipv4Address>::Deserialize (Buffer::Iterator start) |
+{ |
+ Buffer::Iterator i= start; |
+ |
+ ReadFrom (i,m_id); |
+ m_status = i.ReadU8(); |
+ m_range = i.ReadNtohU32(); |
+ if (PositionInRnsHeader) |
+ { |
+ m_x = i.ReadNtohU32(); |
+ m_y = i.ReadNtohU32(); |
+ } |
+ m_entriesNumber = i.ReadNtohU32(); |
+ for (uint32_t k = 0; k < m_entriesNumber; k++) |
+ { |
+ Ipv4Address addr; |
+ ReadFrom(i,addr); |
+ m_rrns.push_back(addr); |
+ } |
+ |
+ |
+ uint32_t dist = i.GetDistanceFrom(start); |
+ NS_ASSERT(dist == GetSerializedSize()); |
+ return dist; |
+} |
+ |
+#ifndef IPV4_REGISTERED |
+#define IPV4_REGISTERED |
+typedef class RnsHeader<Ipv4Address> RnsHeaderIpv4AddressImpl; |
+NS_OBJECT_ENSURE_REGISTERED (RnsHeaderIpv4AddressImpl); |
+typedef class Rns<Ipv4Address> RnsIpv4AddressImpl; |
+NS_OBJECT_ENSURE_REGISTERED(RnsIpv4AddressImpl); |
+#endif |
+ |
+ |
+ |
+/* uint32_t specialization */ |
+ |
+template <> TypeId Rns<uint32_t>::GetTypeId(void) |
+{ |
+ static TypeId tid = TypeId ("ns3::rns::RnsUint32Impl") |
+ .SetParent<Object> () |
+ .AddConstructor<Rns<uint32_t> > () |
+ .AddAttribute("Test","Set to true for testing.", |
+ BooleanValue(false), |
+ MakeBooleanAccessor(&Rns<uint32_t>::IsTest), |
+ MakeBooleanChecker()) |
+ .AddAttribute("ConnectivityMaintenanceMode","Use automatic radio range estimation and maintain network's connectivity.", |
+ BooleanValue(false), |
+ MakeBooleanAccessor(&Rns<uint32_t>::ConnectivityMaintenanceMode), |
+ MakeBooleanChecker()) |
+ .AddAttribute("EventTriggerredBroadcast","Whether Rns broadcast should be triggerred by events or by timer", |
+ BooleanValue(false), |
+ MakeBooleanAccessor(&Rns<uint32_t>::EventTrigerredBroadcast), |
+ MakeBooleanChecker()) |
+ .AddAttribute("UpdateInterval","Interval between automatic Rns updates; Rns message is sent only if EventTriggerBroadcast is set to false.", |
+ TimeValue(Seconds(1.0)), |
+ MakeTimeAccessor(&Rns<uint32_t>::UpdateInterval), |
+ MakeTimeChecker()) |
+ .AddAttribute("MaxEntryAge","The age at which a node's position, range and status are regarded out of date.", |
+ TimeValue(Seconds(100)), |
+ MakeTimeAccessor(&Rns<uint32_t>::MaxEntryAge), |
+ MakeTimeChecker()) |
+ .AddAttribute("UpdateIntervalTimeScatter","Time scatter of Update Interval to avoid collision.", |
+ DoubleValue(100), |
+ MakeDoubleAccessor(&Rns<uint32_t>::UpdateIntervalTimeScatter), |
+ MakeDoubleChecker<double>()) |
+ .AddAttribute ("RangeEstimationAccuracy","How accurate should the range estimation be [m].", |
+ DoubleValue (0.01), |
+ MakeDoubleAccessor (&Rns<uint32_t>::RangeEstimationAccuracy), |
+ MakeDoubleChecker<double> ()) |
+ .AddAttribute ("ProtocolPeriodicUpdate","Whether the protocol will provide a periodic update on neighbors situation.", |
+ BooleanValue(false), |
+ MakeBooleanAccessor(&Rns<uint32_t>::ProtocolPeriodicUpdate), |
+ MakeBooleanChecker()) |
+ .AddAttribute ("PositionInRnsHeader","Whether position information has to be passed in RNS header.", |
+ BooleanValue(true), |
+ MakeBooleanAccessor(&Rns<uint32_t>::PositionInRnsHeader), |
+ MakeBooleanChecker()) |
+ ; |
+ return tid; |
+} |
+ |
+template <> |
+void Rns<uint32_t>::Start(Ptr<Node> node) |
+{ |
+ m_node = node; |
+ |
+ if (IsTest) |
+ { |
+ PositionInRnsHeader = false; |
+ m_protocolUpdate = MakeNullCallback<void, Neighbor<uint32_t> > (); |
+ return; |
+ } |
+ |
+ m_broadcastTimer.SetFunction(&Rns<uint32_t>::UpdateTimerExpire,this); |
+ m_broadcastTimer.Schedule(UpdateInterval - |
+ Time (MilliSeconds (UniformVariable ().GetInteger (0, 10))/100.0)); |
+ |
+ m_agingTimer.SetFunction(&Rns<uint32_t>::AgingTimerExpire,this); |
+ m_agingTimer.Schedule(Seconds (1)); |
+ m_neighbors.SetMaxAge(MaxEntryAge); |
+ |
+ SetRanges(); |
+} |
+ |
+template <> |
+void Rns<uint32_t>::Ipv4Receive (Ptr<Socket> socket) |
+{ |
+ NS_FATAL_ERROR("Ipv4Receive message used with uint32_t IdType."); |
+} |
+ |
+template <> |
+void Rns<uint32_t>::Ipv4Send (RnsHeader<uint32_t> h) |
+{ |
+ NS_FATAL_ERROR("Ipv4Send message used with uint32_t IdType."); |
+} |
+ |
+template <> |
+uint32_t Rns<uint32_t>::Ipv4ToNodeNumber(uint32_t addr) const |
+{ |
+ return 0; |
+} |
+ |
+template <> |
+uint32_t NeighborsTable<uint32_t>::Ipv4ToNodeNumber(uint32_t addr) const |
+{ |
+ return addr; |
+} |
+ |
+template <> |
+uint32_t Neighbor<uint32_t>::Ipv4ToNodeNumber(uint32_t addr) const |
+{ |
+ return addr; |
+} |
+ |
+template <> |
+TypeId RnsHeader<uint32_t>::GetTypeId (void) |
+{ |
+ static TypeId tid = TypeId ("ns3::rns::RnsHeaderU32") |
+ .SetParent<Header> () |
+ .AddConstructor<RnsHeader>(); |
+ return tid; |
+} |
+ |
+template <> |
+uint32_t RnsHeader<uint32_t>::GetSerializedSize () const |
+{ |
+ uint32_t size = 1 + sizeof(uint32_t) + 4; //status + id + range |
+ if (PositionInRnsHeader) |
+ { |
+ size += 8; // + position |
+ } |
+ size += sizeof(uint32_t); //entries_number |
+ size += m_entriesNumber*sizeof(uint32_t); |
+ return size; |
+} |
+ |
+template <> |
+void RnsHeader<uint32_t>::Serialize (Buffer::Iterator start) const |
+{ |
+ start.WriteHtonU32(m_id); |
+ start.WriteU8(m_status); |
+ start.WriteHtonU32(m_range); |
+ if (PositionInRnsHeader) |
+ { |
+ start.WriteHtonU32(m_x); |
+ start.WriteHtonU32(m_y); |
+ } |
+ start.WriteHtonU32(m_entriesNumber); |
+ for (std::vector<uint32_t>::const_iterator i = m_rrns.begin(); |
+ i != m_rrns.end(); i++) |
+ { |
+ start.WriteHtonU32(*i); |
+ } |
+} |
+ |
+template <> |
+uint32_t RnsHeader<uint32_t>::Deserialize (Buffer::Iterator start) |
+{ |
+ Buffer::Iterator i= start; |
+ |
+ m_id = i.ReadNtohU32(); |
+ m_status = i.ReadU8(); |
+ m_range = i.ReadNtohU32(); |
+ if (PositionInRnsHeader) |
+ { |
+ m_x = i.ReadNtohU32(); |
+ m_y = i.ReadNtohU32(); |
+ } |
+ m_entriesNumber = i.ReadNtohU32(); |
+ for (uint32_t k = 0; k < m_entriesNumber; k++) |
+ { |
+ uint32_t addr; |
+ addr = i.ReadNtohU32(); |
+ m_rrns.push_back(addr); |
+ } |
+ |
+ uint32_t dist = i.GetDistanceFrom(start); |
+ NS_ASSERT(dist == GetSerializedSize()); |
+ return dist; |
+} |
+ |
+ |
+ |
+ |
+#ifndef UINT32_REGISTERED |
+#define UINT32_REGISTERED |
+typedef class RnsHeader<uint32_t> RnsHeaderUint32Impl; |
+NS_OBJECT_ENSURE_REGISTERED (RnsHeaderUint32Impl); |
+typedef class Rns<uint32_t> RnsUint32Impl; |
+NS_OBJECT_ENSURE_REGISTERED(RnsUint32Impl); |
+#endif |
+ |
+} // namespace rns |
+/* Helper constructor specializations */ |
+ |
+template <> RnsHelper<Ipv4Address>::RnsHelper () |
+{ |
+ m_agentFactory.SetTypeId ("ns3::rns::RnsIpv4AddressImpl"); |
+} |
+ |
+template <> RnsHelper<uint32_t>::RnsHelper () |
+{ |
+ m_agentFactory.SetTypeId ("ns3::rns::RnsUint32Impl"); |
+} |
+ |
+ |
+ |
+} // namespace ns3 |