A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 (auto 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 return (sequenceControl >> 4) == (m_lastSequenceControl >> 4) &&
138 (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1);
139 }
140
146 uint16_t GetLastSequenceControl() const
147 {
149 }
150
156 void SetSequenceControl(uint16_t sequenceControl)
157 {
158 m_lastSequenceControl = sequenceControl;
159 }
160};
161
163{
165}
166
168{
170 for (auto i = m_originatorStatus.begin(); i != m_originatorStatus.end(); i++)
171 {
172 delete (*i).second;
173 }
175 for (auto i = m_qosOriginatorStatus.begin(); i != m_qosOriginatorStatus.end(); i++)
176 {
177 delete (*i).second;
178 }
180}
181
182void
184{
186 m_callback = callback;
187}
188
191{
192 NS_LOG_FUNCTION(hdr);
193 OriginatorRxStatus* originator;
194 Mac48Address source = hdr->GetAddr2();
195 if (hdr->IsQosData() && !hdr->GetAddr2().IsGroup())
196 {
197 /* only for QoS data non-broadcast frames */
198 originator = m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid())];
199 if (originator == nullptr)
200 {
201 originator = new OriginatorRxStatus();
202 m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid())] = originator;
203 }
204 }
205 else
206 {
207 /* - management frames
208 * - QoS data broadcast frames
209 * - non-QoS data frames
210 * see section 7.1.3.4.1
211 */
212 originator = m_originatorStatus[source];
213 if (originator == nullptr)
214 {
215 originator = new OriginatorRxStatus();
216 m_originatorStatus[source] = originator;
217 }
218 }
219 return originator;
220}
221
222bool
224{
225 NS_LOG_FUNCTION(hdr << originator);
226 return hdr->IsRetry() && originator->GetLastSequenceControl() == hdr->GetSequenceControl();
227}
228
231 const WifiMacHeader* hdr,
232 OriginatorRxStatus* originator)
233{
234 NS_LOG_FUNCTION(packet << hdr << originator);
235 if (originator->IsDeFragmenting())
236 {
237 if (hdr->IsMoreFragments())
238 {
239 if (originator->IsNextFragment(hdr->GetSequenceControl()))
240 {
241 NS_LOG_DEBUG("accumulate fragment seq=" << hdr->GetSequenceNumber()
242 << ", frag=" << +hdr->GetFragmentNumber()
243 << ", size=" << packet->GetSize());
244 originator->AccumulateFragment(packet);
245 originator->SetSequenceControl(hdr->GetSequenceControl());
246 }
247 else
248 {
249 NS_LOG_DEBUG("non-ordered fragment");
250 }
251 return nullptr;
252 }
253 else
254 {
255 if (originator->IsNextFragment(hdr->GetSequenceControl()))
256 {
257 NS_LOG_DEBUG("accumulate last fragment seq="
258 << hdr->GetSequenceNumber() << ", frag=" << +hdr->GetFragmentNumber()
259 << ", size=" << hdr->GetSize());
260 Ptr<Packet> p = originator->AccumulateLastFragment(packet);
261 originator->SetSequenceControl(hdr->GetSequenceControl());
262 return p;
263 }
264 else
265 {
266 NS_LOG_DEBUG("non-ordered fragment");
267 return nullptr;
268 }
269 }
270 }
271 else
272 {
273 if (hdr->IsMoreFragments())
274 {
275 NS_LOG_DEBUG("accumulate first fragment seq=" << hdr->GetSequenceNumber()
276 << ", frag=" << +hdr->GetFragmentNumber()
277 << ", size=" << packet->GetSize());
278 originator->AccumulateFirstFragment(packet);
279 originator->SetSequenceControl(hdr->GetSequenceControl());
280 return nullptr;
281 }
282 else
283 {
284 return packet;
285 }
286 }
287}
288
289void
291{
292 NS_LOG_FUNCTION(*mpdu << +linkId);
293 // consider the MAC header of the original MPDU (makes a difference for data frames only)
294 const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
295 NS_ASSERT(hdr->IsData() || hdr->IsMgt());
296
297 OriginatorRxStatus* originator = Lookup(hdr);
307 if (!(SequenceNumber16(originator->GetLastSequenceControl()) <
309 {
310 NS_LOG_DEBUG("Sequence numbers have looped back. last recorded="
311 << originator->GetLastSequenceControl()
312 << " currently seen=" << hdr->GetSequenceControl());
313 }
314 // filter duplicates.
315 if (IsDuplicate(hdr, originator))
316 {
317 NS_LOG_DEBUG("duplicate from=" << hdr->GetAddr2() << ", seq=" << hdr->GetSequenceNumber()
318 << ", frag=" << +hdr->GetFragmentNumber());
319 return;
320 }
321 Ptr<const Packet> aggregate = HandleFragments(mpdu->GetPacket(), hdr, originator);
322 if (!aggregate)
323 {
324 return;
325 }
326 NS_LOG_DEBUG("forwarding data from=" << hdr->GetAddr2() << ", seq=" << hdr->GetSequenceNumber()
327 << ", frag=" << +hdr->GetFragmentNumber());
328 if (!hdr->GetAddr1().IsGroup())
329 {
330 originator->SetSequenceControl(hdr->GetSequenceControl());
331 }
332 if (aggregate == mpdu->GetPacket())
333 {
334 m_callback(mpdu, linkId);
335 }
336 else
337 {
338 // We could do this in all cases, but passing the received mpdu in case of
339 // A-MSDUs saves us the time to deaggregate the A-MSDU in MSDUs (which are
340 // kept separate in the received mpdu) and allows us to pass the originally
341 // transmitted packets (i.e., with the same UID) to the receiver.
342 m_callback(Create<WifiMpdu>(aggregate, *hdr), linkId);
343 }
344}
345
346} // namespace ns3
an EUI-48 address
Definition: mac48-address.h:46
bool IsGroup() const
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...
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.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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.
virtual 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.