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
33/**
34 * A class to keep track of the packet originator status.
35 * It recomposes the packet from multiple fragments.
36 */
38{
39 private:
40 /**
41 * typedef for a list of fragments (i.e. incomplete Packet).
42 */
43 typedef std::list<Ptr<const Packet>> Fragments;
44 /**
45 * typedef for a const iterator for Fragments
46 */
47 typedef std::list<Ptr<const Packet>>::const_iterator FragmentsCI;
48
49 bool m_defragmenting; ///< flag to indicate whether we are defragmenting
50 uint16_t m_lastSequenceControl; ///< last sequence control
51 Fragments m_fragments; ///< fragments
52
53 public:
55 {
56 /* this is a magic value necessary. */
57 m_lastSequenceControl = 0xffff;
58 m_defragmenting = false;
59 }
60
61 /**
62 * Check if we are de-fragmenting packets.
63 *
64 * \return true if we are de-fragmenting packets,
65 * false otherwise
66 */
67 bool IsDeFragmenting() const
68 {
69 return m_defragmenting;
70 }
71
72 /**
73 * We have received a first fragmented packet.
74 * We start the deframentation by saving the first fragment.
75 *
76 * \param packet the first fragmented packet
77 */
79 {
81 m_defragmenting = true;
82 m_fragments.push_back(packet);
83 }
84
85 /**
86 * We have received a last fragment of the fragmented packets
87 * (indicated by the no more fragment field).
88 * We re-construct the packet from the fragments we saved
89 * and return the full packet.
90 *
91 * \param packet the last fragment
92 *
93 * \return the fully reconstructed packet
94 */
96 {
98 m_fragments.push_back(packet);
99 m_defragmenting = false;
100 Ptr<Packet> full = Create<Packet>();
101 for (auto 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 }
108
109 /**
110 * We received a fragmented packet (not first and not last).
111 * We simply save it into our internal list.
112 *
113 * \param packet the received fragment
114 */
116 {
118 m_fragments.push_back(packet);
119 }
120
121 /**
122 * Check if the sequence control (i.e. fragment number) is
123 * in order.
124 *
125 * \param sequenceControl the raw sequence control
126 *
127 * \return true if the sequence control is in order,
128 * false otherwise
129 */
130 bool IsNextFragment(uint16_t sequenceControl) const
131 {
132 return (sequenceControl >> 4) == (m_lastSequenceControl >> 4) &&
133 (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1);
134 }
135
136 /**
137 * Return the last sequence control we received.
138 *
139 * \return the last sequence control
140 */
141 uint16_t GetLastSequenceControl() const
142 {
144 }
145
146 /**
147 * Set the last sequence control we received.
148 *
149 * \param sequenceControl the last sequence control we received
150 */
151 void SetSequenceControl(uint16_t sequenceControl)
152 {
153 m_lastSequenceControl = sequenceControl;
154 }
155};
156
158{
160}
161
163{
165}
166
167void
169{
171 m_callback = callback;
172}
173
176{
177 NS_LOG_FUNCTION(hdr);
178 const auto source = hdr.GetAddr2();
179 if (hdr.IsQosData() && !source.IsGroup())
180 {
181 /* only for QoS data non-broadcast frames */
182 const auto key = std::make_pair(source, hdr.GetQosTid());
183 auto [it, inserted] = m_qosOriginatorStatus.try_emplace(key);
184 return it->second;
185 }
186 /* - management frames
187 * - QoS data broadcast frames
188 * - non-QoS data frames
189 * see section 7.1.3.4.1
190 */
191 auto [it, inserted] = m_originatorStatus.try_emplace(source);
192 return it->second;
193}
194
195bool
197{
198 NS_LOG_FUNCTION(hdr << &originator);
199 return hdr.IsRetry() && originator.GetLastSequenceControl() == hdr.GetSequenceControl();
200}
201
204 const WifiMacHeader& hdr,
205 OriginatorRxStatus& originator)
206{
207 NS_LOG_FUNCTION(packet << hdr << &originator);
208 if (originator.IsDeFragmenting())
209 {
210 if (hdr.IsMoreFragments())
211 {
212 if (originator.IsNextFragment(hdr.GetSequenceControl()))
213 {
214 NS_LOG_DEBUG("accumulate fragment seq=" << hdr.GetSequenceNumber()
215 << ", frag=" << +hdr.GetFragmentNumber()
216 << ", size=" << packet->GetSize());
217 originator.AccumulateFragment(packet);
218 originator.SetSequenceControl(hdr.GetSequenceControl());
219 }
220 else
221 {
222 NS_LOG_DEBUG("non-ordered fragment");
223 }
224 return nullptr;
225 }
226 else
227 {
228 if (originator.IsNextFragment(hdr.GetSequenceControl()))
229 {
230 NS_LOG_DEBUG("accumulate last fragment seq=" << hdr.GetSequenceNumber() << ", frag="
231 << +hdr.GetFragmentNumber()
232 << ", size=" << hdr.GetSize());
233 Ptr<Packet> p = originator.AccumulateLastFragment(packet);
234 originator.SetSequenceControl(hdr.GetSequenceControl());
235 return p;
236 }
237 else
238 {
239 NS_LOG_DEBUG("non-ordered fragment");
240 return nullptr;
241 }
242 }
243 }
244 else
245 {
246 if (hdr.IsMoreFragments())
247 {
248 NS_LOG_DEBUG("accumulate first fragment seq=" << hdr.GetSequenceNumber()
249 << ", frag=" << +hdr.GetFragmentNumber()
250 << ", size=" << packet->GetSize());
251 originator.AccumulateFirstFragment(packet);
252 originator.SetSequenceControl(hdr.GetSequenceControl());
253 return nullptr;
254 }
255 else
256 {
257 return packet;
258 }
259 }
260}
261
262void
264{
265 NS_LOG_FUNCTION(*mpdu << +linkId);
266 // consider the MAC header of the original MPDU (makes a difference for data frames only)
267 const auto& hdr = mpdu->GetOriginal()->GetHeader();
268 NS_ASSERT(hdr.IsData() || hdr.IsMgt());
269
270 auto& originator = Lookup(hdr);
271 /**
272 * The check below is really unneeded because it can fail in a lot of
273 * normal cases. Specifically, it is possible for sequence numbers to
274 * loop back to zero once they reach 0xfff0 and to go up to 0xf7f0 in
275 * which case the check below will report the two sequence numbers to
276 * not have the correct order relationship.
277 * So, this check cannot be used to discard old duplicate frames. It is
278 * thus here only for documentation purposes.
279 */
280 if (!(SequenceNumber16(originator.GetLastSequenceControl()) <
281 SequenceNumber16(hdr.GetSequenceControl())))
282 {
283 NS_LOG_DEBUG("Sequence numbers have looped back. last recorded="
284 << originator.GetLastSequenceControl()
285 << " currently seen=" << hdr.GetSequenceControl());
286 }
287 // filter duplicates.
288 if (IsDuplicate(hdr, originator))
289 {
290 NS_LOG_DEBUG("duplicate from=" << hdr.GetAddr2() << ", seq=" << hdr.GetSequenceNumber()
291 << ", frag=" << +hdr.GetFragmentNumber());
292 return;
293 }
294 Ptr<const Packet> aggregate = HandleFragments(mpdu->GetPacket(), hdr, originator);
295 if (!aggregate)
296 {
297 return;
298 }
299 NS_LOG_DEBUG("forwarding data from=" << hdr.GetAddr2() << ", seq=" << hdr.GetSequenceNumber()
300 << ", frag=" << +hdr.GetFragmentNumber());
301 if (!hdr.GetAddr1().IsGroup())
302 {
303 originator.SetSequenceControl(hdr.GetSequenceControl());
304 }
305 if (aggregate == mpdu->GetPacket())
306 {
307 m_callback(mpdu, linkId);
308 }
309 else
310 {
311 // We could do this in all cases, but passing the received mpdu in case of
312 // A-MSDUs saves us the time to deaggregate the A-MSDU in MSDUs (which are
313 // kept separate in the received mpdu) and allows us to pass the originally
314 // transmitted packets (i.e., with the same UID) to the receiver.
315 m_callback(Create<WifiMpdu>(aggregate, hdr), linkId);
316 }
317}
318
319} // namespace ns3
void SetForwardCallback(ForwardUpCallback callback)
Set a callback to forward the packet up.
bool IsDuplicate(const WifiMacHeader &hdr, const OriginatorRxStatus &originator) const
Check if we have already received the packet from the sender before (by looking at the sequence contr...
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.
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.
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.
virtual uint32_t GetSize() const
Return the size of the WifiMacHeader in octets.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
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.