A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
wifi-mac-queue.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005, 2009 INRIA
4  * Copyright (c) 2009 MIRKO BANCHI
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Author: Mirko Banchi <mk.banchi@gmail.com>
21  */
22 
23 #include "ns3/simulator.h"
24 #include "ns3/packet.h"
25 #include "ns3/uinteger.h"
26 #include "ns3/log.h"
27 
28 #include "wifi-mac-queue.h"
29 #include "qos-blocked-destinations.h"
30 
31 namespace ns3 {
32 
33 NS_OBJECT_ENSURE_REGISTERED (WifiMacQueue);
34 
35 WifiMacQueue::Item::Item (Ptr<const Packet> packet,
36  const WifiMacHeader &hdr,
37  Time tstamp)
38  : packet (packet),
39  hdr (hdr),
40  tstamp (tstamp)
41 {
42 }
43 
44 WifiMacQueue::Item::Item (Ptr<const Packet> packet,
45  const WifiMacHeader &hdr,
46  Time tstamp, uint16_t channel)
47  : packet (packet),
48  hdr (hdr),
49  tstamp (tstamp),
50  channel (channel)
51 {
52 }
53 
54 TypeId
55 WifiMacQueue::GetTypeId (void)
56 {
57  static TypeId tid = TypeId ("ns3::WifiMacQueue")
58  .SetParent<Object> ()
59  .AddConstructor<WifiMacQueue> ()
60  .AddAttribute ("MaxPacketNumber", "If a packet arrives when there are already this number of packets, it is dropped.",
61  UintegerValue (400),
62  MakeUintegerAccessor (&WifiMacQueue::m_maxSize),
63  MakeUintegerChecker<uint32_t> ())
64  .AddAttribute ("MaxDelay", "If a packet stays longer than this delay in the queue, it is dropped.",
65  TimeValue (Seconds (10.0)),
66  MakeTimeAccessor (&WifiMacQueue::m_maxDelay),
67  MakeTimeChecker ())
68  ;
69  return tid;
70 }
71 
72 WifiMacQueue::WifiMacQueue ()
73  : m_size (0)
74 {
75 }
76 
77 WifiMacQueue::~WifiMacQueue ()
78 {
79  Flush ();
80 }
81 
82 void
83 WifiMacQueue::SetMaxSize (uint32_t maxSize)
84 {
85  m_maxSize = maxSize;
86 }
87 
88 void
89 WifiMacQueue::SetMaxDelay (Time delay)
90 {
91  m_maxDelay = delay;
92 }
93 
94 uint32_t
95 WifiMacQueue::GetMaxSize (void) const
96 {
97  return m_maxSize;
98 }
99 
100 Time
101 WifiMacQueue::GetMaxDelay (void) const
102 {
103  return m_maxDelay;
104 }
105 
106 void
107 WifiMacQueue::Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr)
108 {
109  Cleanup ();
110  if (m_size == m_maxSize)
111  {
112  return;
113  }
114  Time now = Simulator::Now ();
115  PacketChannelPacketTag cpt;
116  packet->PeekPacketTag(cpt);
117  m_queue.push_back (Item (packet, hdr, now, cpt.GetChannel()));
118  m_size++;
119 }
120 
121 void
122 WifiMacQueue::Cleanup (void)
123 {
124  if (m_queue.empty ())
125  {
126  return;
127  }
128 
129  Time now = Simulator::Now ();
130  uint32_t n = 0;
131  for (PacketQueueI i = m_queue.begin (); i != m_queue.end ();)
132  {
133  if (i->tstamp + m_maxDelay > now)
134  {
135  i++;
136  }
137  else
138  {
139  i = m_queue.erase (i);
140  n++;
141  }
142  }
143  m_size -= n;
144 }
145 
146 Ptr<const Packet>
147 WifiMacQueue::Dequeue (WifiMacHeader *hdr)
148 {
149  Cleanup ();
150  if (!m_queue.empty ())
151  {
152  Item i = m_queue.front ();
153  m_queue.pop_front ();
154  m_size--;
155  *hdr = i.hdr;
156  return i.packet;
157  }
158  return 0;
159 }
160 
161 Ptr<const Packet>
162 WifiMacQueue::DequeueForChannel (WifiMacHeader *hdr, uint16_t toChannel)
163 {
164  Cleanup ();
165  Ptr<const Packet> packet = 0;
166  int i=0;
167  if (!m_queue.empty ())
168  {
169  PacketQueueI it;
170  for (it = m_queue.begin (); it != m_queue.end (); ++it)
171  {
172  i++;
173  packet = it->packet;
174  if (it->channel == toChannel ||
175  (it->channel == 0 && toChannel == 1))
176  {
177  *hdr = it->hdr;
178  m_queue.erase(it);
179  m_size--;
180  break;
181  }
182  }
183  }
184  return packet;
185 }
186 
187 Ptr<const Packet>
188 WifiMacQueue::Peek (WifiMacHeader *hdr)
189 {
190  Cleanup ();
191  if (!m_queue.empty ())
192  {
193  Item i = m_queue.front ();
194  *hdr = i.hdr;
195  return i.packet;
196  }
197  return 0;
198 }
199 
200 Ptr<const Packet>
202  WifiMacHeader::AddressType type, Mac48Address dest)
203 {
204  Cleanup ();
205  Ptr<const Packet> packet = 0;
206  if (!m_queue.empty ())
207  {
208  PacketQueueI it;
209  NS_ASSERT (type <= 4);
210  for (it = m_queue.begin (); it != m_queue.end (); ++it)
211  {
212  if (it->hdr.IsQosData ())
213  {
214  if (GetAddressForPacket (type, it) == dest
215  && it->hdr.GetQosTid () == tid)
216  {
217  packet = it->packet;
218  *hdr = it->hdr;
219  m_queue.erase (it);
220  m_size--;
221  break;
222  }
223  }
224  }
225  }
226  return packet;
227 }
228 
231  WifiMacHeader::AddressType type, Mac48Address dest)
232 {
233  Cleanup ();
234  if (!m_queue.empty ())
235  {
236  PacketQueueI it;
237  NS_ASSERT (type <= 4);
238  for (it = m_queue.begin (); it != m_queue.end (); ++it)
239  {
240  if (it->hdr.IsQosData ())
241  {
242  if (GetAddressForPacket (type, it) == dest
243  && it->hdr.GetQosTid () == tid)
244  {
245  *hdr = it->hdr;
246  return it->packet;
247  }
248  }
249  }
250  }
251  return 0;
252 }
253 
254 bool
255 WifiMacQueue::IsEmpty (void)
256 {
257  Cleanup ();
258  return m_queue.empty ();
259 }
260 bool
261 WifiMacQueue::IsEmpty (uint16_t toChannel)
262 {
263  bool empty = true;
264  if (!m_queue.empty())
265  {
266  //Check if any packet exists with destination chan (toChannel)
267  PacketQueueI it;
268  for (it = m_queue.begin (); it != m_queue.end (); ++it)
269  {
270  if (it->channel == toChannel)
271  {
272  empty = false;
273  break;
274  }
279  if (it->channel == 0 && toChannel == 1)
280  {
281  empty = false;
282  break;
283  }
284 
285  }
286  }
287  else return true;
288 
289  return empty;
290 }
291 
292 uint32_t
293 WifiMacQueue::GetSize (void)
294 {
295  return m_size;
296 }
297 
298 void
299 WifiMacQueue::Flush (void)
300 {
301  m_queue.erase (m_queue.begin (), m_queue.end ());
302  m_size = 0;
303 }
304 
305 Mac48Address
306 WifiMacQueue::GetAddressForPacket (enum WifiMacHeader::AddressType type, PacketQueueI it)
307 {
308  if (type == WifiMacHeader::ADDR1)
309  {
310  return it->hdr.GetAddr1 ();
311  }
312  if (type == WifiMacHeader::ADDR2)
313  {
314  return it->hdr.GetAddr2 ();
315  }
316  if (type == WifiMacHeader::ADDR3)
317  {
318  return it->hdr.GetAddr3 ();
319  }
320  return 0;
321 }
322 
323 bool
325 {
326  PacketQueueI it = m_queue.begin ();
327  for (; it != m_queue.end (); it++)
328  {
329  if (it->packet == packet)
330  {
331  m_queue.erase (it);
332  m_size--;
333  return true;
334  }
335  }
336  return false;
337 }
338 
339 void
340 WifiMacQueue::PushFront (Ptr<const Packet> packet, const WifiMacHeader &hdr)
341 {
342  Cleanup ();
343  if (m_size == m_maxSize)
344  {
345  return;
346  }
347  Time now = Simulator::Now ();
348  m_queue.push_front (Item (packet, hdr, now));
349  m_size++;
350 }
351 
352 uint32_t
353 WifiMacQueue::GetNPacketsByTidAndAddress (uint8_t tid, WifiMacHeader::AddressType type,
354  Mac48Address addr)
355 {
356  Cleanup ();
357  uint32_t nPackets = 0;
358  if (!m_queue.empty ())
359  {
360  PacketQueueI it;
361  NS_ASSERT (type <= 4);
362  for (it = m_queue.begin (); it != m_queue.end (); it++)
363  {
364  if (GetAddressForPacket (type, it) == addr)
365  {
366  if (it->hdr.IsQosData () && it->hdr.GetQosTid () == tid)
367  {
368  nPackets++;
369  }
370  }
371  }
372  }
373  return nPackets;
374 }
375 
378  const QosBlockedDestinations *blockedPackets)
379 {
380  Cleanup ();
381  Ptr<const Packet> packet = 0;
382  for (PacketQueueI it = m_queue.begin (); it != m_queue.end (); it++)
383  {
384  if (!it->hdr.IsQosData ()
385  || !blockedPackets->IsBlocked (it->hdr.GetAddr1 (), it->hdr.GetQosTid ()))
386  {
387  *hdr = it->hdr;
388  timestamp = it->tstamp;
389  packet = it->packet;
390  m_queue.erase (it);
391  m_size--;
392  return packet;
393  }
394  }
395  return packet;
396 }
397 
400  const QosBlockedDestinations *blockedPackets)
401 {
402  Cleanup ();
403  for (PacketQueueI it = m_queue.begin (); it != m_queue.end (); it++)
404  {
405  if (!it->hdr.IsQosData ()
406  || !blockedPackets->IsBlocked (it->hdr.GetAddr1 (), it->hdr.GetQosTid ()))
407  {
408  *hdr = it->hdr;
409  timestamp = it->tstamp;
410  return it->packet;
411  }
412  }
413  return 0;
414 }
415 
416 } // namespace ns3
keep track of time unit.
Definition: nstime.h:149
#define NS_ASSERT(condition)
Definition: assert.h:64
Ptr< const Packet > PeekByTidAndAddress(WifiMacHeader *hdr, uint8_t tid, WifiMacHeader::AddressType type, Mac48Address addr)
uint32_t GetNPacketsByTidAndAddress(uint8_t tid, WifiMacHeader::AddressType type, Mac48Address addr)
bool Remove(Ptr< const Packet > packet)
Ptr< const Packet > DequeueFirstAvailable(WifiMacHeader *hdr, Time &tStamp, const QosBlockedDestinations *blockedPackets)
Ptr< const Packet > DequeueByTidAndAddress(WifiMacHeader *hdr, uint8_t tid, WifiMacHeader::AddressType type, Mac48Address addr)
make Callback use a separate empty type
Definition: empty.h:8
an EUI-48 address
Definition: mac48-address.h:41
static Time Now(void)
Definition: simulator.cc:179
Ptr< const Packet > PeekFirstAvailable(WifiMacHeader *hdr, Time &tStamp, const QosBlockedDestinations *blockedPackets)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586