Index: src/devices/mesh/flame/flame-protocol.cc |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/devices/mesh/flame/flame-protocol.cc |
@@ -0,0 +1,377 @@ |
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
+/* |
+ * Copyright (c) 2009 IITP RAS |
+ * |
+ * 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: Kirill Andreev <andreev@iitp.ru> |
+ */ |
+ |
+#include "flame-protocol.h" |
+#include "flame-protocol-mac.h" |
+#include "flame-header.h" |
+#include "flame-rtable.h" |
+#include "ns3/llc-snap-header.h" |
+#include "ns3/log.h" |
+#include "ns3/simulator.h" |
+#include "ns3/packet.h" |
+#include "ns3/mesh-point-device.h" |
+#include "ns3/wifi-net-device.h" |
+#include "ns3/mesh-point-device.h" |
+#include "ns3/mesh-wifi-interface-mac.h" |
+#include "ns3/random-variable.h" |
+ |
+NS_LOG_COMPONENT_DEFINE ("FlameProtocol"); |
+ |
+namespace ns3 { |
+namespace flame { |
+//----------------------------------------------------------------------------- |
+// FlameTag |
+//----------------------------------------------------------------------------- |
+NS_OBJECT_ENSURE_REGISTERED (FlameTag); |
+ |
+TypeId |
+FlameTag::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::flame::FlameTag") .SetParent<Tag> () .AddConstructor<FlameTag> (); |
+ return tid; |
+} |
+ |
+TypeId |
+FlameTag::GetInstanceTypeId () const |
+{ |
+ return GetTypeId (); |
+} |
+ |
+uint32_t |
+FlameTag::GetSerializedSize () const |
+{ |
+ return 12; |
+} |
+ |
+void |
+FlameTag::Serialize (TagBuffer i) const |
+{ |
+ uint8_t buf[6]; |
+ receiver.CopyTo (buf); |
+ for (int j = 0; j < 6; j++) |
+ { |
+ i.WriteU8 (buf[j]); |
+ } |
+ transmitter.CopyTo (buf); |
+ for (int j = 0; j < 6; j++) |
+ { |
+ i.WriteU8 (buf[j]); |
+ } |
+ |
+} |
+ |
+void |
+FlameTag::Deserialize (TagBuffer i) |
+{ |
+ uint8_t buf[6]; |
+ for (int j = 0; j < 6; j++) |
+ { |
+ buf[j] = i.ReadU8 (); |
+ } |
+ receiver.CopyFrom (buf); |
+ for (int j = 0; j < 6; j++) |
+ { |
+ buf[j] = i.ReadU8 (); |
+ } |
+ transmitter.CopyFrom (buf); |
+ |
+} |
+ |
+void |
+FlameTag::Print (std::ostream &os) const |
+{ |
+ os << "receiver = " << receiver << ", transmitter = " << transmitter; |
+} |
+ |
+//----------------------------------------------------------------------------- |
+// FlameProtocol |
+//----------------------------------------------------------------------------- |
+TypeId |
+FlameProtocol::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::flame::FlameProtocol") |
+ .SetParent<MeshL2RoutingProtocol> () |
+ .AddConstructor<FlameProtocol> () |
+ .AddAttribute ( "BroadcastInterval", |
+ "How often we must send broadcast packets", |
+ TimeValue (Seconds (5)), |
+ MakeTimeAccessor ( |
+ &FlameProtocol::m_broadcastInterval), |
+ MakeTimeChecker () |
+ ) |
+ .AddAttribute ( "MaxCost", |
+ "Cost threshold after which packet will be dropeed", |
+ UintegerValue (32), |
+ MakeUintegerAccessor ( |
+ &FlameProtocol::m_maxCost), |
+ MakeUintegerChecker<uint8_t> (3) |
+ ) |
+ ; |
+ return tid; |
+} |
+FlameProtocol::FlameProtocol () : |
+ m_address (Mac48Address ()), m_broadcastInterval (Seconds (5)), m_lastBroadcast (Simulator::Now ()), |
+ m_maxCost (32), m_myLastSeqno (1), m_rtable (CreateObject<FlameRtable> ()) |
+{ |
+} |
+FlameProtocol::~FlameProtocol () |
+{ |
+} |
+void |
+FlameProtocol::DoDispose () |
+{ |
+} |
+bool |
+FlameProtocol::RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination, |
+ Ptr<const Packet> const_packet, uint16_t protocolType, RouteReplyCallback routeReply) |
+{ |
+ Ptr<Packet> packet = const_packet->Copy (); |
+ if (sourceIface == m_mp->GetIfIndex ()) |
+ { |
+ //Packet from upper layer! |
+ FlameTag tag; |
+ if (packet->PeekPacketTag (tag)) |
+ { |
+ NS_FATAL_ERROR ("FLAME tag is not supposed to be received from upper layers"); |
+ } |
+ FlameRtable::LookupResult result = m_rtable->Lookup (destination); |
+ if (result.retransmitter == Mac48Address::GetBroadcast ()) |
+ { |
+ m_lastBroadcast = Simulator::Now (); |
+ } |
+ if (m_lastBroadcast + m_broadcastInterval < Simulator::Now ()) |
+ { |
+ result.retransmitter = Mac48Address::GetBroadcast (); |
+ result.ifIndex = FlameRtable::INTERFACE_ANY; |
+ m_lastBroadcast = Simulator::Now (); |
+ } |
+ FlameHeader flameHdr; |
+ flameHdr.AddCost (0); |
+ flameHdr.SetSeqno (m_myLastSeqno++); |
+ flameHdr.SetProtocol (protocolType); |
+ flameHdr.SetOrigDst (destination); |
+ flameHdr.SetOrigSrc (source); |
+ m_stats.txBytes += packet->GetSize (); |
+ packet->AddHeader (flameHdr); |
+ tag.receiver = result.retransmitter; |
+ if (result.retransmitter == Mac48Address::GetBroadcast ()) |
+ { |
+ m_stats.txBroadcast++; |
+ } |
+ else |
+ { |
+ m_stats.txUnicast++; |
+ } |
+ NS_LOG_DEBUG ("Source: send packet with RA = " << tag.receiver); |
+ packet->AddPacketTag (tag); |
+ routeReply (true, packet, source, destination, FLAME_PROTOCOL, result.ifIndex); |
+ } |
+ else |
+ { |
+ FlameHeader flameHdr; |
+ packet->RemoveHeader (flameHdr); |
+ FlameTag tag; |
+ |
+ if (!packet->RemovePacketTag (tag)) |
+ { |
+ NS_FATAL_ERROR ("FLAME tag must exist here"); |
+ } |
+ if (destination == Mac48Address::GetBroadcast ()) |
+ { |
+ //Broadcast always is forwarded as broadcast! |
+ NS_ASSERT (HandleDataFrame (flameHdr.GetSeqno (), source, flameHdr, tag.transmitter, sourceIface)); |
+ FlameTag tag (Mac48Address::GetBroadcast ()); |
+ flameHdr.AddCost (1); |
+ m_stats.txBytes += packet->GetSize (); |
+ packet->AddHeader (flameHdr); |
+ packet->AddPacketTag (tag); |
+ routeReply (true, packet, source, destination, FLAME_PROTOCOL, FlameRtable::INTERFACE_ANY); |
+ m_stats.txBroadcast++; |
+ return true; |
+ } |
+ else |
+ { |
+ // We check sequence only when forward unicast, because broadcast-checks were done |
+ // inside remove routing stuff. |
+ if (HandleDataFrame (flameHdr.GetSeqno (), source, flameHdr, tag.transmitter, sourceIface)) |
+ { |
+ return false; |
+ } |
+ FlameRtable::LookupResult result = m_rtable->Lookup (destination); |
+ if (tag.receiver != Mac48Address::GetBroadcast ()) |
+ { |
+ if (result.retransmitter == Mac48Address::GetBroadcast ()) |
+ { |
+ NS_LOG_DEBUG ("unicast packet dropped, because no route! I am " << GetAddress () |
+ << ", RA = " << tag.receiver << ", TA = " << tag.transmitter); |
+ m_stats.totalDropped++; |
+ return false; |
+ } |
+ } |
+ tag.receiver = result.retransmitter; |
+ if (result.retransmitter == Mac48Address::GetBroadcast ()) |
+ { |
+ m_stats.txBroadcast++; |
+ } |
+ else |
+ { |
+ m_stats.txUnicast++; |
+ } |
+ m_stats.txBytes += packet->GetSize (); |
+ flameHdr.AddCost (1); |
+ packet->AddHeader (flameHdr); |
+ packet->AddPacketTag (tag); |
+ routeReply (true, packet, source, destination, FLAME_PROTOCOL, result.ifIndex); |
+ return true; |
+ } |
+ return true; |
+ } |
+ return false; |
+} |
+bool |
+FlameProtocol::RemoveRoutingStuff (uint32_t fromIface, const Mac48Address source, |
+ const Mac48Address destination, Ptr<Packet> packet, uint16_t& protocolType) |
+{ |
+ //Filter seqno: |
+ if (source == GetAddress ()) |
+ { |
+ NS_LOG_DEBUG ("Dropped my own frame!"); |
+ return false; |
+ } |
+ FlameTag tag; |
+ if (!packet->RemovePacketTag (tag)) |
+ { |
+ NS_FATAL_ERROR ("FLAME tag must exist when packet is coming to protocol"); |
+ } |
+ FlameHeader flameHdr; |
+ packet->RemoveHeader (flameHdr); |
+ if ((destination == GetAddress ()) && (m_lastBroadcast + m_broadcastInterval < Simulator::Now ())) |
+ { |
+ Ptr<Packet> packet = Create<Packet> (); |
+ m_mp->Send(packet, Mac48Address::GetBroadcast (), 0); |
+ m_lastBroadcast = Simulator::Now (); |
+ } |
+ NS_ASSERT (protocolType == FLAME_PROTOCOL); |
+ protocolType = flameHdr.GetProtocol (); |
+ if ((HandleDataFrame (flameHdr.GetSeqno (), source, flameHdr, tag.transmitter, fromIface)) |
+ || packet->GetSize () == 0) |
+ { |
+ return false; |
+ } |
+ return true; |
+} |
+bool |
+FlameProtocol::Install (Ptr<MeshPointDevice> mp) |
+{ |
+ m_mp = mp; |
+ std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces (); |
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = interfaces.begin (); i != interfaces.end (); i++) |
+ { |
+ // Checking for compatible net device |
+ Ptr<WifiNetDevice> wifiNetDev = (*i)->GetObject<WifiNetDevice> (); |
+ if (wifiNetDev == 0) |
+ { |
+ return false; |
+ } |
+ Ptr<MeshWifiInterfaceMac> mac = wifiNetDev->GetMac ()->GetObject<MeshWifiInterfaceMac> (); |
+ if (mac == 0) |
+ { |
+ return false; |
+ } |
+ // Installing plugins: |
+ Ptr<FlameProtocolMac> flameMac = Create<FlameProtocolMac> (wifiNetDev->GetIfIndex (), this); |
+ m_interfaces[wifiNetDev->GetIfIndex ()] = flameMac; |
+ mac->SetBeaconGeneration (false); |
+ mac->InstallPlugin (flameMac); |
+ } |
+ mp->SetRoutingProtocol (this); |
+ // Mesh point aggregates all installed protocols |
+ mp->AggregateObject (this); |
+ m_address = Mac48Address::ConvertFrom (mp->GetAddress ());//* address; |
+ return true; |
+} |
+Mac48Address |
+FlameProtocol::GetAddress () |
+{ |
+ return m_address; |
+} |
+bool |
+FlameProtocol::HandleDataFrame (uint16_t seqno, Mac48Address source, const FlameHeader flameHdr, |
+ Mac48Address receiver, uint32_t fromInterface) |
+{ |
+ if (source == GetAddress ()) |
+ { |
+ m_stats.totalDropped++; |
+ return true; |
+ } |
+ FlameRtable::LookupResult result = m_rtable->Lookup (source); |
+ if ((result.retransmitter != Mac48Address::GetBroadcast ()) && ((int16_t)(result.seqnum - seqno) >= 0)) |
+ { |
+ return true; |
+ } |
+ if (flameHdr.GetCost () > m_maxCost) |
+ { |
+ m_stats.droppedTtl++; |
+ return true; |
+ } |
+ m_rtable->AddPath (source, receiver, fromInterface, flameHdr.GetCost (), flameHdr.GetSeqno ()); |
+ return false; |
+} |
+//Statistics: |
+FlameProtocol::Statistics::Statistics () : |
+ txUnicast (0), txBroadcast (0), txBytes (0), droppedTtl (0), totalDropped (0) |
+{ |
+} |
+void |
+FlameProtocol::Statistics::Print (std::ostream & os) const |
+{ |
+ os << "<Statistics " |
+ "txUnicast=\"" << txUnicast << "\" " |
+ "txBroadcast=\"" << txBroadcast << "\" " |
+ "txBytes=\"" << txBytes << "\" " |
+ "droppedTtl=\"" << droppedTtl << "\" " |
+ "totalDropped=\"" << totalDropped << "\"/>" << std::endl; |
+} |
+void |
+FlameProtocol::Report (std::ostream & os) const |
+{ |
+ os << "<Flame " |
+ "address=\"" << m_address << "\"" << std::endl << |
+ "broadcastInterval=\"" << m_broadcastInterval.GetSeconds () << "\"" << std::endl << |
+ "maxCost=\"" << (uint16_t) m_maxCost << "\">" << std::endl; |
+ m_stats.Print (os); |
+ for (FlamePluginMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin++) |
+ { |
+ plugin->second->Report (os); |
+ } |
+ os << "</Flame>" << std::endl; |
+} |
+void |
+FlameProtocol::ResetStats () |
+{ |
+ m_stats = Statistics (); |
+ for (FlamePluginMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin++) |
+ { |
+ plugin->second->ResetStats (); |
+ } |
+} |
+ |
+} //namespace flame |
+} //namespace ns3 |