A Discrete-Event Network Simulator
API
mac-rx-middle.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19
20#include "mac-rx-middle.h"
21
22#include "wifi-mpdu.h"
23
24#include "ns3/log.h"
25#include "ns3/packet.h"
26#include "ns3/sequence-number.h"
27
28namespace ns3
29{
30
31NS_LOG_COMPONENT_DEFINE("MacRxMiddle");
32
38{
39 private:
43 typedef std::list<Ptr<const Packet>> Fragments;
47 typedef std::list<Ptr<const Packet>>::const_iterator FragmentsCI;
48
52
53 public:
55 {
56 /* this is a magic value necessary. */
57 m_lastSequenceControl = 0xffff;
58 m_defragmenting = false;
59 }
60
62 {
63 m_fragments.clear();
64 }
65
72 bool IsDeFragmenting() const
73 {
74 return m_defragmenting;
75 }
76
84 {
86 m_defragmenting = true;
87 m_fragments.push_back(packet);
88 }
89
101 {
103 m_fragments.push_back(packet);
104 m_defragmenting = false;
105 Ptr<Packet> full = Create<Packet>();
106 for (FragmentsCI i = m_fragments.begin(); i != m_fragments.end(); i++)
107 {
108 full->AddAtEnd(*i);
109 }
110 m_fragments.erase(m_fragments.begin(), m_fragments.end());
111 return full;
112 }
113
121 {
123 m_fragments.push_back(packet);
124 }
125
135 bool IsNextFragment(uint16_t sequenceControl) const
136 {
137 if ((sequenceControl >> 4) == (m_lastSequenceControl >> 4) &&
138 (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1))
139 {
140 return true;
141 }
142 else
143 {
144 return false;
145 }
146 }
147
153 uint16_t GetLastSequenceControl() const
154 {
156 }
157
163 void SetSequenceControl(uint16_t sequenceControl)
164 {
165 m_lastSequenceControl = sequenceControl;
166 }
167};
168
170{
172}
173
175{
177 for (OriginatorsI i = m_originatorStatus.begin(); i != m_originatorStatus.end(); i++)
178 {
179 delete (*i).second;
180 }
182 for (QosOriginatorsI i = m_qosOriginatorStatus.begin(); i != m_qosOriginatorStatus.end(); i++)
183 {
184 delete (*i).second;
185 }
187}
188
189void
191{
193 m_callback = callback;
194}
195
198{
199 NS_LOG_FUNCTION(hdr);
200 OriginatorRxStatus* originator;
201 Mac48Address source = hdr->GetAddr2();
202 if (hdr->IsQosData() && !hdr->GetAddr2().IsGroup())
203 {
204 /* only for QoS data non-broadcast frames */
205 originator = m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid())];
206 if (originator == nullptr)
207 {
208 originator = new OriginatorRxStatus();
209 m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid())] = originator;
210 }
211 }
212 else
213 {
214 /* - management frames
215 * - QoS data broadcast frames
216 * - non-QoS data frames
217 * see section 7.1.3.4.1
218 */
219 originator = m_originatorStatus[source];
220 if (originator == nullptr)
221 {
222 originator = new OriginatorRxStatus();
223 m_originatorStatus[source] = originator;
224 }
225 }
226 return originator;
227}
228
229bool
231{
232 NS_LOG_FUNCTION(hdr << originator);
233 if (hdr->IsRetry() && originator->GetLastSequenceControl() == hdr->GetSequenceControl())
234 {
235 return true;
236 }
237 return false;
238}
239
242 const WifiMacHeader* hdr,
243 OriginatorRxStatus* originator)
244{
245 NS_LOG_FUNCTION(packet << hdr << originator);
246 if (originator->IsDeFragmenting())
247 {
248 if (hdr->IsMoreFragments())
249 {
250 if (originator->IsNextFragment(hdr->GetSequenceControl()))
251 {
252 NS_LOG_DEBUG("accumulate fragment seq=" << hdr->GetSequenceNumber()
253 << ", frag=" << +hdr->GetFragmentNumber()
254 << ", size=" << packet->GetSize());
255 originator->AccumulateFragment(packet);
256 originator->SetSequenceControl(hdr->GetSequenceControl());
257 }
258 else
259 {
260 NS_LOG_DEBUG("non-ordered fragment");
261 }
262 return nullptr;
263 }
264 else
265 {
266 if (originator->IsNextFragment(hdr->GetSequenceControl()))
267 {
268 NS_LOG_DEBUG("accumulate last fragment seq="
269 << hdr->GetSequenceNumber() << ", frag=" << +hdr->GetFragmentNumber()
270 << ", size=" << hdr->GetSize());
271 Ptr<Packet> p = originator->AccumulateLastFragment(packet);
272 originator->SetSequenceControl(hdr->GetSequenceControl());
273 return p;
274 }
275 else
276 {
277 NS_LOG_DEBUG("non-ordered fragment");
278 return nullptr;
279 }
280 }
281 }
282 else
283 {
284 if (hdr->IsMoreFragments())
285 {
286 NS_LOG_DEBUG("accumulate first fragment seq=" << hdr->GetSequenceNumber()
287 << ", frag=" << +hdr->GetFragmentNumber()
288 << ", size=" << packet->GetSize());
289 originator->AccumulateFirstFragment(packet);
290 originator->SetSequenceControl(hdr->GetSequenceControl());
291 return nullptr;
292 }
293 else
294 {
295 return packet;
296 }
297 }
298}
299
300void
302{
303 NS_LOG_FUNCTION(*mpdu << +linkId);
304 const WifiMacHeader* hdr = &mpdu->GetHeader();
305 NS_ASSERT(hdr->IsData() || hdr->IsMgt());
306
307 OriginatorRxStatus* originator = Lookup(hdr);
317 if (!(SequenceNumber16(originator->GetLastSequenceControl()) <
319 {
320 NS_LOG_DEBUG("Sequence numbers have looped back. last recorded="
321 << originator->GetLastSequenceControl()
322 << " currently seen=" << hdr->GetSequenceControl());
323 }
324 // filter duplicates.
325 if (IsDuplicate(hdr, originator))
326 {
327 NS_LOG_DEBUG("duplicate from=" << hdr->GetAddr2() << ", seq=" << hdr->GetSequenceNumber()
328 << ", frag=" << +hdr->GetFragmentNumber());
329 return;
330 }
331 Ptr<const Packet> aggregate = HandleFragments(mpdu->GetPacket(), hdr, originator);
332 if (!aggregate)
333 {
334 return;
335 }
336 NS_LOG_DEBUG("forwarding data from=" << hdr->GetAddr2() << ", seq=" << hdr->GetSequenceNumber()
337 << ", frag=" << +hdr->GetFragmentNumber());
338 if (!hdr->GetAddr1().IsGroup())
339 {
340 originator->SetSequenceControl(hdr->GetSequenceControl());
341 }
342 if (aggregate == mpdu->GetPacket())
343 {
344 m_callback(mpdu, linkId);
345 }
346 else
347 {
348 // We could do this in all cases, but passing the received mpdu in case of
349 // A-MSDUs saves us the time to deaggregate the A-MSDU in MSDUs (which are
350 // kept separate in the received mpdu) and allows us to pass the originally
351 // transmitted packets (i.e., with the same UID) to the receiver.
352 m_callback(Create<WifiMpdu>(aggregate, *hdr), linkId);
353 }
354}
355
356} // namespace ns3
an EUI-48 address
Definition: mac48-address.h:46
bool IsGroup() 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
void Receive(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
Receive an MPDU on the given link.
QosOriginators m_qosOriginatorStatus
QOS originator status.
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.
bool IsDeFragmenting() const
Check if we are de-fragmenting packets.
std::list< Ptr< constPacket > >::const_iterator FragmentsCI
typedef for a const iterator for Fragments
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.
uint16_t GetLastSequenceControl() const
Return the last sequence control we received.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
Generic "sequence number" class.
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
uint16_t GetSequenceNumber() const
Return the sequence number of the header.
bool IsMoreFragments() const
Return if the More Fragment bit is set.
uint16_t GetSequenceControl() const
Return the raw Sequence Control field.
bool IsRetry() const
Return if the Retry bit is set.
bool IsMgt() const
Return true if the Type is Management.
uint32_t GetSize() const
Return the size of the WifiMacHeader in octets.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool IsData() const
Return true if the Type is DATA.
uint8_t GetFragmentNumber() const
Return the fragment number of the header.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
#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
#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
#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 ",...
SequenceNumber< uint16_t, int16_t > SequenceNumber16
16 bit Sequence number.
Every class exported by the ns3 library is enclosed in the ns3 namespace.