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 "ns3/log.h"
22#include "ns3/sequence-number.h"
23#include "ns3/packet.h"
24#include "mac-rx-middle.h"
25#include "wifi-mac-queue-item.h"
26
27namespace ns3 {
28
29NS_LOG_COMPONENT_DEFINE ("MacRxMiddle");
30
36{
37private:
41 typedef std::list<Ptr<const Packet> > Fragments;
45 typedef std::list<Ptr<const Packet> >::const_iterator FragmentsCI;
46
50
51
52public:
54 {
55 /* this is a magic value necessary. */
56 m_lastSequenceControl = 0xffff;
57 m_defragmenting = false;
58 }
60 {
61 m_fragments.clear ();
62 }
69 bool IsDeFragmenting (void) const
70 {
71 return m_defragmenting;
72 }
80 {
82 m_defragmenting = true;
83 m_fragments.push_back (packet);
84 }
96 {
98 m_fragments.push_back (packet);
99 m_defragmenting = false;
100 Ptr<Packet> full = Create<Packet> ();
101 for (FragmentsCI i = m_fragments.begin (); i != m_fragments.end (); i++)
102 {
103 full->AddAtEnd (*i);
104 }
105 m_fragments.erase (m_fragments.begin (), m_fragments.end ());
106 return full;
107 }
115 {
117 m_fragments.push_back (packet);
118 }
128 bool IsNextFragment (uint16_t sequenceControl) const
129 {
130 if ((sequenceControl >> 4) == (m_lastSequenceControl >> 4)
131 && (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1))
132 {
133 return true;
134 }
135 else
136 {
137 return false;
138 }
139 }
145 uint16_t GetLastSequenceControl (void) const
146 {
148 }
154 void SetSequenceControl (uint16_t sequenceControl)
155 {
156 m_lastSequenceControl = sequenceControl;
157 }
158};
159
160
162{
164}
165
167{
169 for (OriginatorsI i = m_originatorStatus.begin ();
170 i != m_originatorStatus.end (); i++)
171 {
172 delete (*i).second;
173 }
175 m_originatorStatus.end ());
176 for (QosOriginatorsI i = m_qosOriginatorStatus.begin ();
177 i != m_qosOriginatorStatus.end (); i++)
178 {
179 delete (*i).second;
180 }
182 m_qosOriginatorStatus.end ());
183}
184
185void
187{
189 m_callback = callback;
190}
191
194{
195 NS_LOG_FUNCTION (hdr);
196 OriginatorRxStatus *originator;
197 Mac48Address source = hdr->GetAddr2 ();
198 if (hdr->IsQosData ()
199 && !hdr->GetAddr2 ().IsGroup ())
200 {
201 /* only for QoS data non-broadcast frames */
202 originator = m_qosOriginatorStatus[std::make_pair (source, hdr->GetQosTid ())];
203 if (originator == 0)
204 {
205 originator = new OriginatorRxStatus ();
206 m_qosOriginatorStatus[std::make_pair (source, hdr->GetQosTid ())] = originator;
207 }
208 }
209 else
210 {
211 /* - management frames
212 * - QoS data broadcast frames
213 * - non-QoS data frames
214 * see section 7.1.3.4.1
215 */
216 originator = m_originatorStatus[source];
217 if (originator == 0)
218 {
219 originator = new OriginatorRxStatus ();
220 m_originatorStatus[source] = originator;
221 }
222 }
223 return originator;
224}
225
226bool
228 OriginatorRxStatus *originator) const
229{
230 NS_LOG_FUNCTION (hdr << originator);
231 if (hdr->IsRetry ()
232 && originator->GetLastSequenceControl () == hdr->GetSequenceControl ())
233 {
234 return true;
235 }
236 return false;
237}
238
241 OriginatorRxStatus *originator)
242{
243 NS_LOG_FUNCTION (packet << hdr << originator);
244 if (originator->IsDeFragmenting ())
245 {
246 if (hdr->IsMoreFragments ())
247 {
248 if (originator->IsNextFragment (hdr->GetSequenceControl ()))
249 {
250 NS_LOG_DEBUG ("accumulate fragment seq=" << hdr->GetSequenceNumber () <<
251 ", frag=" << +hdr->GetFragmentNumber () <<
252 ", size=" << packet->GetSize ());
253 originator->AccumulateFragment (packet);
254 originator->SetSequenceControl (hdr->GetSequenceControl ());
255 }
256 else
257 {
258 NS_LOG_DEBUG ("non-ordered fragment");
259 }
260 return 0;
261 }
262 else
263 {
264 if (originator->IsNextFragment (hdr->GetSequenceControl ()))
265 {
266 NS_LOG_DEBUG ("accumulate last fragment seq=" << hdr->GetSequenceNumber () <<
267 ", frag=" << +hdr->GetFragmentNumber () <<
268 ", size=" << hdr->GetSize ());
269 Ptr<Packet> p = originator->AccumulateLastFragment (packet);
270 originator->SetSequenceControl (hdr->GetSequenceControl ());
271 return p;
272 }
273 else
274 {
275 NS_LOG_DEBUG ("non-ordered fragment");
276 return 0;
277 }
278 }
279 }
280 else
281 {
282 if (hdr->IsMoreFragments ())
283 {
284 NS_LOG_DEBUG ("accumulate first fragment seq=" << hdr->GetSequenceNumber () <<
285 ", frag=" << +hdr->GetFragmentNumber () <<
286 ", size=" << packet->GetSize ());
287 originator->AccumulateFirstFragment (packet);
288 originator->SetSequenceControl (hdr->GetSequenceControl ());
289 return 0;
290 }
291 else
292 {
293 return packet;
294 }
295 }
296}
297
298void
300{
301 NS_LOG_FUNCTION (*mpdu);
302 const WifiMacHeader* hdr = &mpdu->GetHeader ();
303 NS_ASSERT (hdr->IsData () || hdr->IsMgt ());
304
305 OriginatorRxStatus *originator = Lookup (hdr);
316 {
317 NS_LOG_DEBUG ("Sequence numbers have looped back. last recorded=" << originator->GetLastSequenceControl () <<
318 " currently seen=" << hdr->GetSequenceControl ());
319 }
320 //filter duplicates.
321 if (IsDuplicate (hdr, originator))
322 {
323 NS_LOG_DEBUG ("duplicate from=" << hdr->GetAddr2 () <<
324 ", seq=" << hdr->GetSequenceNumber () <<
325 ", frag=" << +hdr->GetFragmentNumber ());
326 return;
327 }
328 Ptr<const Packet> aggregate = HandleFragments (mpdu->GetPacket (), hdr, originator);
329 if (aggregate == 0)
330 {
331 return;
332 }
333 NS_LOG_DEBUG ("forwarding data from=" << hdr->GetAddr2 () <<
334 ", seq=" << hdr->GetSequenceNumber () <<
335 ", frag=" << +hdr->GetFragmentNumber ());
336 if (!hdr->GetAddr1 ().IsGroup ())
337 {
338 originator->SetSequenceControl (hdr->GetSequenceControl ());
339 }
340 if (aggregate == mpdu->GetPacket ())
341 {
342 m_callback (mpdu);
343 }
344 else
345 {
346 // We could do this in all cases, but passing the received mpdu in case of
347 // A-MSDUs saves us the time to deaggregate the A-MSDU in MSDUs (which are
348 // kept separate in the received mpdu) and allows us to pass the originally
349 // transmitted packets (i.e., with the same UID) to the receiver.
350 m_callback (Create<WifiMacQueueItem> (aggregate, *hdr));
351 }
352}
353
354} //namespace ns3
an EUI-48 address
Definition: mac48-address.h:44
bool IsGroup(void) const
std::map< std::pair< Mac48Address, uint8_t >, OriginatorRxStatus *, std::less< std::pair< Mac48Address, uint8_t > > >::iterator QosOriginatorsI
typedef for an iterator for QosOriginators
void SetForwardCallback(ForwardUpCallback callback)
Set a callback to forward the packet up.
Originators m_originatorStatus
originator status
Ptr< const Packet > HandleFragments(Ptr< const Packet > packet, const WifiMacHeader *hdr, OriginatorRxStatus *originator)
Check if the received packet is a fragment and handle it appropriately.
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...
std::map< Mac48Address, OriginatorRxStatus *, std::less< Mac48Address > >::iterator OriginatorsI
typedef for an iterator for Originators
QosOriginators m_qosOriginatorStatus
QOS originator status.
void Receive(Ptr< WifiMacQueueItem > mpdu)
Receive a packet.
ForwardUpCallback m_callback
forward up callback
OriginatorRxStatus * Lookup(const WifiMacHeader *hdr)
Look up for OriginatorRxStatus associated with the sender address (by looking at ADDR2 field in the h...
A class to keep track of the packet originator status.
void AccumulateFragment(Ptr< const Packet > packet)
We received a fragmented packet (not first and not last).
Ptr< Packet > AccumulateLastFragment(Ptr< const Packet > packet)
We have received a last fragment of the fragmented packets (indicated by the no more fragment field).
Fragments m_fragments
fragments
uint16_t m_lastSequenceControl
last sequence control
void SetSequenceControl(uint16_t sequenceControl)
Set the last sequence control we received.
std::list< Ptr< constPacket > >::const_iterator FragmentsCI
typedef for a const iterator for Fragments
uint16_t GetLastSequenceControl(void) const
Return the last sequence control we received.
bool IsDeFragmenting(void) const
Check if we are de-fragmenting packets.
std::list< Ptr< const Packet > > Fragments
typedef for a list of fragments (i.e.
void AccumulateFirstFragment(Ptr< const Packet > packet)
We have received a first fragmented packet.
bool m_defragmenting
flag to indicate whether we are defragmenting
bool IsNextFragment(uint16_t sequenceControl) const
Check if the sequence control (i.e.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
Generic "sequence number" class.
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
bool IsRetry(void) const
Return if the Retry bit is set.
bool IsMgt(void) const
Return true if the Type is Management.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
bool IsData(void) const
Return true if the Type is DATA.
bool IsMoreFragments(void) const
Return if the More Fragment bit is set.
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
uint8_t GetFragmentNumber(void) const
Return the fragment number of the header.
#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:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.