A Discrete-Event Network Simulator
API
mac-rx-middle.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "mac-rx-middle.h"
22 #include "wifi-mac-header.h"
23 #include "ns3/log.h"
24 #include "ns3/sequence-number.h"
25 
26 namespace ns3 {
27 
28 NS_LOG_COMPONENT_DEFINE ("MacRxMiddle");
29 
35 {
36 private:
40  typedef std::list<Ptr<const Packet> > Fragments;
44  typedef std::list<Ptr<const Packet> >::const_iterator FragmentsCI;
45 
48  Fragments m_fragments;
49 
50 
51 public:
53  {
54  /* this is a magic value necessary. */
55  m_lastSequenceControl = 0xffff;
56  m_defragmenting = false;
57  }
59  {
60  m_fragments.clear ();
61  }
68  bool IsDeFragmenting (void) const
69  {
70  return m_defragmenting;
71  }
79  {
80  NS_ASSERT (!m_defragmenting);
81  m_defragmenting = true;
82  m_fragments.push_back (packet);
83  }
95  {
96  NS_ASSERT (m_defragmenting);
97  m_fragments.push_back (packet);
98  m_defragmenting = false;
99  Ptr<Packet> full = Create<Packet> ();
100  for (FragmentsCI i = m_fragments.begin (); i != m_fragments.end (); i++)
101  {
102  full->AddAtEnd (*i);
103  }
104  m_fragments.erase (m_fragments.begin (), m_fragments.end ());
105  return full;
106  }
114  {
115  NS_ASSERT (m_defragmenting);
116  m_fragments.push_back (packet);
117  }
127  bool IsNextFragment (uint16_t sequenceControl) const
128  {
129  if ((sequenceControl >> 4) == (m_lastSequenceControl >> 4)
130  && (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1))
131  {
132  return true;
133  }
134  else
135  {
136  return false;
137  }
138  }
144  uint16_t GetLastSequenceControl (void) const
145  {
146  return m_lastSequenceControl;
147  }
153  void SetSequenceControl (uint16_t sequenceControl)
154  {
155  m_lastSequenceControl = sequenceControl;
156  }
157 };
158 
159 
161 {
163 }
164 
166 {
168  for (OriginatorsI i = m_originatorStatus.begin ();
169  i != m_originatorStatus.end (); i++)
170  {
171  delete (*i).second;
172  }
173  m_originatorStatus.erase (m_originatorStatus.begin (),
174  m_originatorStatus.end ());
175  for (QosOriginatorsI i = m_qosOriginatorStatus.begin ();
176  i != m_qosOriginatorStatus.end (); i++)
177  {
178  delete (*i).second;
179  }
181  m_qosOriginatorStatus.end ());
182 }
183 
184 void
186 {
188  m_callback = callback;
189 }
190 
193 {
194  NS_LOG_FUNCTION (hdr);
195  OriginatorRxStatus *originator;
196  Mac48Address source = hdr->GetAddr2 ();
197  if (hdr->IsQosData ()
198  && !hdr->GetAddr2 ().IsGroup ())
199  {
200  /* only for qos data non-broadcast frames */
201  originator = m_qosOriginatorStatus[std::make_pair (source, hdr->GetQosTid ())];
202  if (originator == 0)
203  {
204  originator = new OriginatorRxStatus ();
205  m_qosOriginatorStatus[std::make_pair (source, hdr->GetQosTid ())] = originator;
206  }
207  }
208  else
209  {
210  /* - management frames
211  * - qos data broadcast frames
212  * - nqos data frames
213  * see section 7.1.3.4.1
214  */
215  originator = m_originatorStatus[source];
216  if (originator == 0)
217  {
218  originator = new OriginatorRxStatus ();
219  m_originatorStatus[source] = originator;
220  }
221  }
222  return originator;
223 }
224 
225 bool
227  OriginatorRxStatus *originator) const
228 {
229  NS_LOG_FUNCTION (hdr << originator);
230  if (hdr->IsRetry ()
231  && originator->GetLastSequenceControl () == hdr->GetSequenceControl ())
232  {
233  return true;
234  }
235  return false;
236 }
237 
240  OriginatorRxStatus *originator)
241 {
242  NS_LOG_FUNCTION (packet << hdr << originator);
243  if (originator->IsDeFragmenting ())
244  {
245  if (hdr->IsMoreFragments ())
246  {
247  if (originator->IsNextFragment (hdr->GetSequenceControl ()))
248  {
249  NS_LOG_DEBUG ("accumulate fragment seq=" << hdr->GetSequenceNumber () <<
250  ", frag=" << hdr->GetFragmentNumber () <<
251  ", size=" << packet->GetSize ());
252  originator->AccumulateFragment (packet);
253  originator->SetSequenceControl (hdr->GetSequenceControl ());
254  }
255  else
256  {
257  NS_LOG_DEBUG ("non-ordered fragment");
258  }
259  return 0;
260  }
261  else
262  {
263  if (originator->IsNextFragment (hdr->GetSequenceControl ()))
264  {
265  NS_LOG_DEBUG ("accumulate last fragment seq=" << hdr->GetSequenceNumber () <<
266  ", frag=" << hdr->GetFragmentNumber () <<
267  ", size=" << hdr->GetSize ());
268  Ptr<Packet> p = originator->AccumulateLastFragment (packet);
269  originator->SetSequenceControl (hdr->GetSequenceControl ());
270  return p;
271  }
272  else
273  {
274  NS_LOG_DEBUG ("non-ordered fragment");
275  return 0;
276  }
277  }
278  }
279  else
280  {
281  if (hdr->IsMoreFragments ())
282  {
283  NS_LOG_DEBUG ("accumulate first fragment seq=" << hdr->GetSequenceNumber () <<
284  ", frag=" << hdr->GetFragmentNumber () <<
285  ", size=" << packet->GetSize ());
286  originator->AccumulateFirstFragment (packet);
287  originator->SetSequenceControl (hdr->GetSequenceControl ());
288  return 0;
289  }
290  else
291  {
292  return packet;
293  }
294  }
295 }
296 
297 void
299 {
300  NS_LOG_FUNCTION (packet << hdr);
301  NS_ASSERT (hdr->IsData () || hdr->IsMgt ());
302  OriginatorRxStatus *originator = Lookup (hdr);
312  if (!(SequenceNumber16 (originator->GetLastSequenceControl ()) < SequenceNumber16 (hdr->GetSequenceControl ())))
313  {
314  NS_LOG_DEBUG ("Sequence numbers have looped back. last recorded=" << originator->GetLastSequenceControl () <<
315  " currently seen=" << hdr->GetSequenceControl ());
316  }
317  //filter duplicates.
318  if (IsDuplicate (hdr, originator))
319  {
320  NS_LOG_DEBUG ("duplicate from=" << hdr->GetAddr2 () <<
321  ", seq=" << hdr->GetSequenceNumber () <<
322  ", frag=" << hdr->GetFragmentNumber ());
323  return;
324  }
325  Ptr<Packet> agregate = HandleFragments (packet, hdr, originator);
326  if (agregate == 0)
327  {
328  return;
329  }
330  NS_LOG_DEBUG ("forwarding data from=" << hdr->GetAddr2 () <<
331  ", seq=" << hdr->GetSequenceNumber () <<
332  ", frag=" << hdr->GetFragmentNumber ());
333  if (!hdr->GetAddr1 ().IsGroup ())
334  {
335  originator->SetSequenceControl (hdr->GetSequenceControl ());
336  }
337  m_callback (agregate, hdr);
338 }
339 
340 } //namespace ns3
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint16_t GetFragmentNumber(void) const
Return the fragment number of the header.
void AccumulateFirstFragment(Ptr< const Packet > packet)
We have received a first fragmented packet.
uint16_t m_lastSequenceControl
last sequence control
void SetForwardCallback(ForwardUpCallback callback)
Set a callback to forward the packet up.
Fragments m_fragments
fragments
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:796
std::map< std::pair< Mac48Address, uint8_t >, OriginatorRxStatus *, std::less< std::pair< Mac48Address, uint8_t > > >::iterator QosOriginatorsI
typedef for an interator for QosOriginators
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
bool IsNextFragment(uint16_t sequenceControl) const
Check if the sequence control (i.e.
void Receive(Ptr< Packet > packet, const WifiMacHeader *hdr)
Receive a packet.
Ptr< Packet > HandleFragments(Ptr< Packet > packet, const WifiMacHeader *hdr, OriginatorRxStatus *originator)
Check if the received packet is a fragment and handle it appropriately.
bool IsMoreFragments(void) const
Return if the More Fragment bit is set.
std::map< Mac48Address, OriginatorRxStatus *, std::less< Mac48Address > >::iterator OriginatorsI
typedef for an interator for Originators
void AccumulateFragment(Ptr< const Packet > packet)
We received a fragmented packet (not first and not last).
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:312
OriginatorRxStatus * Lookup(const WifiMacHeader *hdr)
Look up for OriginatorRxStatus associated with the sender address (by looking at ADDR2 field in the h...
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
Originators m_originatorStatus
originator status
bool IsDuplicate(const WifiMacHeader *hdr, OriginatorRxStatus *originator) const
Check if we have already received the packet from the sender before (by looking at the sequence contr...
bool IsMgt(void) const
Return true if the Type is Management.
uint16_t GetLastSequenceControl(void) const
Return the last sequence control we received.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Generic "sequence number" class.
bool IsGroup(void) const
Ptr< Packet > AccumulateLastFragment(Ptr< const Packet > packet)
We have received a last fragment of the fragmented packets (indicated by the no more fragment field)...
void SetSequenceControl(uint16_t sequenceControl)
Set the last sequence control we received.
an EUI-48 address
Definition: mac48-address.h:43
bool m_defragmenting
flag to indicate whether we are defragmenting
std::list< Ptr< const Packet > > Fragments
typedef for a list of fragments (i.e.
bool IsData(void) const
Return true if the Type is DATA.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
ForwardUpCallback m_callback
forward up callback
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:269
std::list< Ptr< const Packet > >::const_iterator FragmentsCI
typedef for a const iterator for Fragments
bool IsDeFragmenting(void) const
Check if we are de-fragmenting packets.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
A class to keep track of the packet originator status.
QosOriginators m_qosOriginatorStatus
QOS originator status.
bool IsRetry(void) const
Return if the Retry bit is set.
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.