A Discrete-Event Network Simulator
API
flame-protocol.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 IITP RAS
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Kirill Andreev <andreev@iitp.ru>
18  */
19 
20 #include "flame-protocol.h"
21 
22 #include "flame-header.h"
23 #include "flame-protocol-mac.h"
24 #include "flame-rtable.h"
25 
26 #include "ns3/llc-snap-header.h"
27 #include "ns3/log.h"
28 #include "ns3/mesh-point-device.h"
29 #include "ns3/mesh-wifi-interface-mac.h"
30 #include "ns3/packet.h"
31 #include "ns3/simulator.h"
32 #include "ns3/wifi-net-device.h"
33 
34 namespace ns3
35 {
36 
37 NS_LOG_COMPONENT_DEFINE("FlameProtocol");
38 
39 namespace flame
40 {
41 
42 //-----------------------------------------------------------------------------
43 // FlameTag
44 //-----------------------------------------------------------------------------
46 NS_OBJECT_ENSURE_REGISTERED(FlameProtocol);
47 
48 TypeId
50 {
51  static TypeId tid = TypeId("ns3::flame::FlameTag")
52  .SetParent<Tag>()
53  .SetGroupName("Mesh")
54  .AddConstructor<FlameTag>();
55  return tid;
56 }
57 
58 TypeId
60 {
61  return GetTypeId();
62 }
63 
64 uint32_t
66 {
67  return 12;
68 }
69 
70 void
72 {
73  uint8_t buf[6];
74  receiver.CopyTo(buf);
75  for (int j = 0; j < 6; j++)
76  {
77  i.WriteU8(buf[j]);
78  }
79  transmitter.CopyTo(buf);
80  for (int j = 0; j < 6; j++)
81  {
82  i.WriteU8(buf[j]);
83  }
84 }
85 
86 void
88 {
89  uint8_t buf[6];
90  for (int j = 0; j < 6; j++)
91  {
92  buf[j] = i.ReadU8();
93  }
94  receiver.CopyFrom(buf);
95  for (int j = 0; j < 6; j++)
96  {
97  buf[j] = i.ReadU8();
98  }
99  transmitter.CopyFrom(buf);
100 }
101 
102 void
103 FlameTag::Print(std::ostream& os) const
104 {
105  os << "receiver = " << receiver << ", transmitter = " << transmitter;
106 }
107 
108 //-----------------------------------------------------------------------------
109 // FlameProtocol
110 //-----------------------------------------------------------------------------
111 TypeId
113 {
114  static TypeId tid = TypeId("ns3::flame::FlameProtocol")
116  .SetGroupName("Mesh")
117  .AddConstructor<FlameProtocol>()
118  .AddAttribute("BroadcastInterval",
119  "How often we must send broadcast packets",
120  TimeValue(Seconds(5)),
122  MakeTimeChecker())
123  .AddAttribute("MaxCost",
124  "Cost threshold after which packet will be dropped",
125  UintegerValue(32),
127  MakeUintegerChecker<uint8_t>(3));
128  return tid;
129 }
130 
132  : m_address(Mac48Address()),
133  m_broadcastInterval(Seconds(5)),
134  m_lastBroadcast(Seconds(0)),
135  m_maxCost(32),
136  m_myLastSeqno(1),
137  m_rtable(CreateObject<FlameRtable>())
138 {
139 }
140 
142 {
143 }
144 
145 void
147 {
148  m_interfaces.clear();
149  m_rtable = nullptr;
150  m_mp = nullptr;
151 }
152 
153 bool
154 FlameProtocol::RequestRoute(uint32_t sourceIface,
155  const Mac48Address source,
156  const Mac48Address destination,
157  Ptr<const Packet> const_packet,
158  uint16_t protocolType,
159  RouteReplyCallback routeReply)
160 {
161  Ptr<Packet> packet = const_packet->Copy();
162  if (sourceIface == m_mp->GetIfIndex())
163  {
164  // Packet from upper layer!
165  FlameTag tag;
166  if (packet->PeekPacketTag(tag))
167  {
168  NS_FATAL_ERROR("FLAME tag is not supposed to be received from upper layers");
169  }
170  FlameRtable::LookupResult result = m_rtable->Lookup(destination);
172  {
174  }
176  {
180  }
181  FlameHeader flameHdr;
182  flameHdr.AddCost(0);
183  flameHdr.SetSeqno(m_myLastSeqno++);
184  flameHdr.SetProtocol(protocolType);
185  flameHdr.SetOrigDst(destination);
186  flameHdr.SetOrigSrc(source);
187  m_stats.txBytes += packet->GetSize();
188  packet->AddHeader(flameHdr);
189  tag.receiver = result.retransmitter;
191  {
193  }
194  else
195  {
196  m_stats.txUnicast++;
197  }
198  NS_LOG_DEBUG("Source: send packet with RA = " << tag.receiver);
199  packet->AddPacketTag(tag);
200  routeReply(true, packet, source, destination, FLAME_PROTOCOL, result.ifIndex);
201  }
202  else
203  {
204  FlameHeader flameHdr;
205  packet->RemoveHeader(flameHdr);
206  FlameTag tag;
207 
208  if (!packet->RemovePacketTag(tag))
209  {
210  NS_FATAL_ERROR("FLAME tag must exist here");
211  }
212  if (destination == Mac48Address::GetBroadcast())
213  {
214  // Broadcast always is forwarded as broadcast!
216  source,
217  flameHdr,
218  tag.transmitter,
219  sourceIface));
221  flameHdr.AddCost(1);
222  m_stats.txBytes += packet->GetSize();
223  packet->AddHeader(flameHdr);
224  packet->AddPacketTag(tag);
225  routeReply(true,
226  packet,
227  source,
228  destination,
232  return true;
233  }
234  else
235  {
236  // We check sequence only when forward unicast, because broadcast-checks were done
237  // inside remove routing stuff.
238  if (HandleDataFrame(flameHdr.GetSeqno(),
239  source,
240  flameHdr,
241  tag.transmitter,
242  sourceIface))
243  {
244  return false;
245  }
246  FlameRtable::LookupResult result = m_rtable->Lookup(destination);
248  {
250  {
251  NS_LOG_DEBUG("unicast packet dropped, because no route! I am "
252  << GetAddress() << ", RA = " << tag.receiver
253  << ", TA = " << tag.transmitter);
255  return false;
256  }
257  tag.receiver = result.retransmitter;
258  }
259  else
260  {
262  }
264  {
266  }
267  else
268  {
269  m_stats.txUnicast++;
270  }
271  m_stats.txBytes += packet->GetSize();
272  flameHdr.AddCost(1);
273  packet->AddHeader(flameHdr);
274  packet->AddPacketTag(tag);
275  routeReply(true, packet, source, destination, FLAME_PROTOCOL, result.ifIndex);
276  return true;
277  }
278  return true;
279  }
280  return false;
281 }
282 
283 bool
285  const Mac48Address source,
286  const Mac48Address destination,
287  Ptr<Packet> packet,
288  uint16_t& protocolType)
289 {
290  // Filter seqno:
291  if (source == GetAddress())
292  {
293  NS_LOG_DEBUG("Dropped my own frame!");
294  return false;
295  }
296  FlameTag tag;
297  if (!packet->RemovePacketTag(tag))
298  {
299  NS_FATAL_ERROR("FLAME tag must exist when packet is coming to protocol");
300  }
301  FlameHeader flameHdr;
302  packet->RemoveHeader(flameHdr);
303  if (HandleDataFrame(flameHdr.GetSeqno(), source, flameHdr, tag.transmitter, fromIface))
304  {
305  return false;
306  }
307  // Start PATH_UPDATE procedure if destination is our own address and last broadcast was sent
308  // more than broadcast interval ago or was not sent at all
309  if ((destination == GetAddress()) &&
311  (m_lastBroadcast == Seconds(0))))
312  {
313  Ptr<Packet> packet = Create<Packet>();
314  m_mp->Send(packet, Mac48Address::GetBroadcast(), 0);
316  }
317  NS_ASSERT(protocolType == FLAME_PROTOCOL);
318  protocolType = flameHdr.GetProtocol();
319  return true;
320 }
321 
322 bool
324 {
325  m_mp = mp;
326  std::vector<Ptr<NetDevice>> interfaces = mp->GetInterfaces();
327  for (std::vector<Ptr<NetDevice>>::const_iterator i = interfaces.begin(); i != interfaces.end();
328  i++)
329  {
330  // Checking for compatible net device
331  Ptr<WifiNetDevice> wifiNetDev = (*i)->GetObject<WifiNetDevice>();
332  if (!wifiNetDev)
333  {
334  return false;
335  }
337  if (!mac)
338  {
339  return false;
340  }
341  // Installing plugins:
342  Ptr<FlameProtocolMac> flameMac = Create<FlameProtocolMac>(this);
343  m_interfaces[wifiNetDev->GetIfIndex()] = flameMac;
344  mac->SetBeaconGeneration(false);
345  mac->InstallPlugin(flameMac);
346  }
347  mp->SetRoutingProtocol(this);
348  // Mesh point aggregates all installed protocols
349  mp->AggregateObject(this);
350  m_address = Mac48Address::ConvertFrom(mp->GetAddress()); //* address;
351  return true;
352 }
353 
356 {
357  return m_address;
358 }
359 
360 bool
362  Mac48Address source,
363  const FlameHeader flameHdr,
364  Mac48Address receiver,
365  uint32_t fromInterface)
366 {
367  if (source == GetAddress())
368  {
370  return true;
371  }
372  FlameRtable::LookupResult result = m_rtable->Lookup(source);
373  if ((result.retransmitter != Mac48Address::GetBroadcast()) &&
374  ((int16_t)(result.seqnum - seqno) >= 0))
375  {
376  return true;
377  }
378  if (flameHdr.GetCost() > m_maxCost)
379  {
381  return true;
382  }
383  m_rtable->AddPath(source, receiver, fromInterface, flameHdr.GetCost(), flameHdr.GetSeqno());
384  return false;
385 }
386 
387 // Statistics:
389  : txUnicast(0),
390  txBroadcast(0),
391  txBytes(0),
392  droppedTtl(0),
393  totalDropped(0)
394 {
395 }
396 
397 void
398 FlameProtocol::Statistics::Print(std::ostream& os) const
399 {
400  os << "<Statistics "
401  "txUnicast=\""
402  << txUnicast
403  << "\" "
404  "txBroadcast=\""
405  << txBroadcast
406  << "\" "
407  "txBytes=\""
408  << txBytes
409  << "\" "
410  "droppedTtl=\""
411  << droppedTtl
412  << "\" "
413  "totalDropped=\""
414  << totalDropped << "\"/>" << std::endl;
415 }
416 
417 void
418 FlameProtocol::Report(std::ostream& os) const
419 {
420  os << "<Flame "
421  "address=\""
422  << m_address << "\"" << std::endl
423  << "broadcastInterval=\"" << m_broadcastInterval.GetSeconds() << "\"" << std::endl
424  << "maxCost=\"" << (uint16_t)m_maxCost << "\">" << std::endl;
425  m_stats.Print(os);
426  for (FlamePluginMap::const_iterator plugin = m_interfaces.begin(); plugin != m_interfaces.end();
427  plugin++)
428  {
429  plugin->second->Report(os);
430  }
431  os << "</Flame>" << std::endl;
432 }
433 
434 void
436 {
437  m_stats = Statistics();
438  for (FlamePluginMap::const_iterator plugin = m_interfaces.begin(); plugin != m_interfaces.end();
439  plugin++)
440  {
441  plugin->second->ResetStats();
442  }
443 }
444 
445 } // namespace flame
446 } // namespace ns3
Callback template class.
Definition: callback.h:443
an EUI-48 address
Definition: mac48-address.h:46
void CopyFrom(const uint8_t buffer[6])
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
void CopyTo(uint8_t buffer[6]) const
Interface for L2 mesh routing protocol and mesh point communication.
Ptr< MeshPointDevice > m_mp
Host mesh point.
Basic MAC of mesh point Wi-Fi interface.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:1002
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
read and write tag data
Definition: tag-buffer.h:52
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
TAG_BUFFER_INLINE uint8_t ReadU8()
Definition: tag-buffer.h:196
tag a set of bytes in a packet
Definition: tag.h:39
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
Hold together all Wifi-related objects.
Ptr< WifiMac > GetMac() const
uint32_t GetIfIndex() const override
uint8_t GetCost() const
Get cost value.
void SetOrigSrc(Mac48Address OrigSrc)
Set origin source function.
void AddCost(uint8_t cost)
Add cost value.
uint16_t GetSeqno() const
Get sequence number value.
void SetOrigDst(Mac48Address dst)
Set origin destination address.
void SetProtocol(uint16_t protocol)
Set protocol value.
uint16_t GetProtocol() const
Get protocol value.
void SetSeqno(uint16_t seqno)
Set sequence number value.
FLAME routing protocol.
bool RemoveRoutingStuff(uint32_t fromIface, const Mac48Address source, const Mac48Address destination, Ptr< Packet > packet, uint16_t &protocolType) override
Cleanup flame headers!
Time m_broadcastInterval
Max Cost value (or TTL, because cost is actually hopcount)
void DoDispose() override
Destructor implementation.
static TypeId GetTypeId()
Get the type ID.
static const uint16_t FLAME_PROTOCOL
LLC protocol number reserved by flame.
bool RequestRoute(uint32_t sourceIface, const Mac48Address source, const Mac48Address destination, Ptr< const Packet > packet, uint16_t protocolType, RouteReplyCallback routeReply) override
Route request, inherited from MeshL2RoutingProtocol.
uint16_t m_myLastSeqno
Sequence number:
Ptr< FlameRtable > m_rtable
Routing table:
bool HandleDataFrame(uint16_t seqno, Mac48Address source, const FlameHeader flameHdr, Mac48Address receiver, uint32_t fromIface)
Handles a packet: adds a routing information and drops packets by TTL or Seqno.
Mac48Address GetAddress()
Get address of this instance.
uint8_t m_maxCost
Max Cost value (or TTL, because cost is actually hopcount)
bool Install(Ptr< MeshPointDevice > mp)
Install FLAME on given mesh point.
Time m_lastBroadcast
Max Cost value (or TTL, because cost is actually hopcount)
Statistics m_stats
statistics
Mac48Address m_address
address
void ResetStats()
Reset statistics function.
void Report(std::ostream &os) const
Statistics.
FlamePluginMap m_interfaces
interfaces
Routing table for FLAME.
Definition: flame-rtable.h:39
LookupResult Lookup(Mac48Address destination)
Lookup path to destination.
Definition: flame-rtable.cc:94
static const uint32_t INTERFACE_ANY
Means all interfaces.
Definition: flame-rtable.h:42
void AddPath(const Mac48Address destination, const Mac48Address retransmitter, const uint32_t interface, const uint8_t cost, const uint16_t seqnum)
Add path.
Definition: flame-rtable.cc:67
Transmitter and receiver addresses.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
void Serialize(TagBuffer i) const override
void Print(std::ostream &os) const override
uint32_t GetSerializedSize() const override
static TypeId GetTypeId()
Get the type ID.
Mac48Address receiver
Receiver of the packet:
Mac48Address transmitter
transmitter for incoming:
void Deserialize(TagBuffer i) override
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:46
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:579
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
interfaces
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
mac
Definition: third.py:85
uint16_t txBroadcast
transmit broadcast
uint16_t txUnicast
transmit unicast
void Print(std::ostream &os) const
Print function.
Route lookup result, return type of LookupXXX methods.
Definition: flame-rtable.h:48
uint16_t seqnum
sequence number
Definition: flame-rtable.h:52
Mac48Address retransmitter
retransmitter
Definition: flame-rtable.h:49