EMANE  1.2.1
ieee80211abg/downstreamqueue.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 - Adjacent Link LLC, Bridgewater, New Jersey
3  * Copyright (c) 2008 - DRS CenGen, LLC, Columbia, Maryland
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of DRS CenGen, LLC nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 
35 #include "downstreamqueue.h"
36 #include "macconfig.h"
37 #include "macstatistics.h"
38 
39 
46  id_{id},
47  numActiveCategories_{MAX_ACCESS_CATEGORIES},
48  pNumUnicastPacketsUnsupported_{},
49  pNumUnicastBytesUnsupported_{},
50  pNumBroadcastPacketsUnsupported_{},
51  pNumBroadcastBytesUnsupported_{}
52 {
53  for(std::uint8_t u8Category = 0; u8Category < MAX_ACCESS_CATEGORIES; ++u8Category)
54  {
55  categories_[u8Category].category_ = u8Category;
56  }
57 }
58 
59 
66 { }
67 
68 
69 
71 {
72  pNumUnicastPacketsUnsupported_ =
73  statisticRegistrar.registerNumeric<std::uint32_t>("numUnicastPacketsUnsupported",
75  pNumUnicastBytesUnsupported_ =
76  statisticRegistrar.registerNumeric<std::uint32_t>("numUnicastBytesUnsupported",
78  pNumBroadcastPacketsUnsupported_ =
79  statisticRegistrar.registerNumeric<std::uint32_t>("numBroadcastPacketsUnsupported",
81  pNumBroadcastBytesUnsupported_ =
82  statisticRegistrar.registerNumeric<std::uint32_t>("numBroadcastBytesUnsupported",
84 
85  for(std::uint8_t u8Category = 0; u8Category < MAX_ACCESS_CATEGORIES; ++u8Category)
86  {
87  categories_[u8Category].registerStatistics(statisticRegistrar);
88  }
89 }
90 
91 
92 
101 void
102 EMANE::Models::IEEE80211ABG::DownstreamQueue::setMaxCapacity(size_t maxEntries, std::uint8_t u8Category)
103 {
104  if(u8Category < numActiveCategories_)
105  {
106  // clear entries that extend past the max limit
107  while(maxEntries < categories_[u8Category].queue_.size())
108  {
109  categories_[u8Category].queue_.pop();
110  }
111 
112  // set new size
113  categories_[u8Category].u8MaxQueueCapacity_ = maxEntries;
114  }
115 }
116 
117 
118 
126 void
128 {
129  for(std::uint8_t u8Category = 0; u8Category < numActiveCategories_; ++u8Category)
130  {
131  // clear entries that extend past the max limit
132  while(maxEntries < categories_[u8Category].queue_.size())
133  {
134  categories_[u8Category].queue_.pop();
135  }
136 
137  // set new size
138  categories_[u8Category].u8MaxQueueCapacity_ = maxEntries;
139  }
140 }
141 
142 
143 
152 void
153 EMANE::Models::IEEE80211ABG::DownstreamQueue::setMaxEntrySize(size_t maxEntrySize, std::uint8_t u8Category)
154 {
155  // set new size
156  categories_[u8Category].u16MaxPacketSize_ = maxEntrySize;
157 }
158 
159 
160 
168 void
170 {
171  for(std::uint8_t u8Category = 0; u8Category < numActiveCategories_; ++u8Category)
172  {
173  // set new size
174  categories_[u8Category].u16MaxPacketSize_ = maxEntrySize;
175  }
176 }
177 
178 
188 size_t
190 {
191  size_t result{};
192 
193  if(u8Category < numActiveCategories_)
194  {
195  result = categories_[u8Category].u8MaxQueueCapacity_;
196  }
197 
198  return result;
199 }
200 
208 size_t
210 {
211  size_t result{};
212 
213  for(std::uint8_t u8Category = 0; u8Category < numActiveCategories_; ++u8Category)
214  {
215  result += categories_[u8Category].u8MaxQueueCapacity_;
216  }
217 
218  return result;
219 }
220 
221 
222 
232 size_t
234 {
235  size_t result{};
236 
237  if(u8Category < numActiveCategories_)
238  {
239  result = categories_[u8Category].queue_.size();
240  }
241 
242  return result;
243 }
244 
252 size_t
254 {
255  size_t result{};
256 
257  for(std::uint8_t u8Category = 0; u8Category < numActiveCategories_; ++u8Category)
258  {
259  result += categories_[u8Category].queue_.size();
260  }
261 
262  return result;
263 }
264 
265 
266 
267 size_t
269 {
270  size_t result{};
271 
272  if(u8Category < numActiveCategories_)
273  {
274  result = categories_[u8Category].u8MaxQueueCapacity_ - categories_[u8Category].queue_.size();
275  }
276 
277  return result;
278 }
279 
280 
281 size_t
283 {
284  size_t result{};
285 
286  // total queue size
287  for(std::uint8_t u8Category = 0; u8Category < numActiveCategories_; ++u8Category)
288  {
289  // space remaining
290  result += categories_[u8Category].u8MaxQueueCapacity_ - categories_[u8Category].queue_.size();
291  }
292 
293  return result;
294 }
295 
296 
297 
305 void
307 {
308  // check min/max range 1 or more
309  if((u8NumCategories > 0) && (u8NumCategories <= MAX_ACCESS_CATEGORIES))
310  {
311  for(std::uint8_t u8Category = u8NumCategories; u8Category < numActiveCategories_; ++u8Category)
312  {
313  // clear queues that will no longer be used
314  while(categories_[numActiveCategories_ - u8Category].queue_.empty() == false)
315  {
316  categories_[numActiveCategories_ - u8Category].queue_.pop();
317  }
318  }
319 
320  // set new size
321  numActiveCategories_ = u8NumCategories;
322  }
323 }
324 
325 
333 std::pair<EMANE::Models::IEEE80211ABG::DownstreamQueueEntry, bool>
335 {
336  // try higher priority first, work down to lower priority
337  for(int iIndex = numActiveCategories_ - 1; iIndex >= 0; --iIndex)
338  {
339  // queue not empty
340  if(categories_[iIndex].queue_.empty() == false)
341  {
342  DownstreamQueueEntry entry{std::move(categories_[iIndex].queue_.front())};
343 
344  // pop entry
345  categories_[iIndex].queue_.pop();
346 
347  return {std::move(entry),true};
348  }
349  }
350 
351  return {DownstreamQueueEntry(),false};
352 }
353 
359 std::vector<EMANE::Models::IEEE80211ABG::DownstreamQueueEntry>
361 {
362  std::vector<DownstreamQueueEntry> result;
363 
364  if(entry.u8Category_ < numActiveCategories_)
365  {
366  AccessCategory * p{&categories_[entry.u8Category_]};
367 
368  // queue disabled if max size for this category is 0
369  if(p->u8MaxQueueCapacity_ == 0)
370  {
371  // add to drop list
372  result.push_back(std::move(entry));
373  }
374  // if max msdu is enabled and entry too large
375  else if((p->u16MaxPacketSize_ != 0) && (entry.pkt_.length() > p->u16MaxPacketSize_))
376  {
377  // bump entry exceeded msdu
379  {
381  p->pNumBroadcastBytesTooLarge_ += entry.pkt_.length();
382  }
383  else
384  {
385  ++*p->pNumUnicastPacketsTooLarge_;
386  *p->pNumUnicastBytesTooLarge_ += entry.pkt_.length();
387  }
388 
389  // add to drop list
390  result.push_back(std::move(entry));
391  }
392  else
393  {
394  // check for queue overflow
395  while(p->queue_.size() >= p->u8MaxQueueCapacity_)
396  {
397  // add to drop list
398  result.push_back(std::move(p->queue_.front()));
399 
400  // pop entry
401  p->queue_.pop();
402  }
403 
404  p->queue_.push(std::move(entry));
405 
406  // bump high water mark
407  if(p->queue_.size() > p->pNumHighWaterMark_->get())
408  {
409  *p->pNumHighWaterMark_ = p->queue_.size();
410  *p->pNumHighWaterMax_ = p->u8MaxQueueCapacity_;
411  }
412  }
413  }
414  else
415  {
417  {
418  ++*pNumBroadcastPacketsUnsupported_;
419  *pNumBroadcastBytesUnsupported_ += entry.pkt_.length();
420  }
421  else
422  {
423  ++*pNumUnicastPacketsUnsupported_;
424  *pNumUnicastBytesUnsupported_ += entry.pkt_.length();
425  }
426 
427  // add to drop list
428  result.push_back(std::move(entry));
429  }
430 
431  return result;
432 }
433 
434 
435 
436 /* @param u8Category queue index
437  * @param bClear clear num discard history
438  *
439  * @retval max number of entries
440  *
441  */
442 size_t
444 {
445  size_t result{};
446 
447  if(u8Category < numActiveCategories_)
448  {
449  result = categories_[u8Category].numPacketOverFlow_;
450 
451  if(bClear == true)
452  {
453  categories_[u8Category].numPacketOverFlow_ = 0;
454  }
455  }
456 
457  return result;
458 }
459 
460 
461 size_t
463 {
464  size_t result{};
465 
466  for(std::uint8_t u8Category = 0; u8Category < numActiveCategories_; ++u8Category)
467  {
468  result += categories_[u8Category].numPacketOverFlow_;
469 
470  if(bClear == true)
471  {
472  categories_[u8Category].numPacketOverFlow_ = 0;
473  }
474  }
475 
476  return result;
477 }
const PacketInfo & getPacketInfo() const
IEEE80211abgDownstreamPacketQueue queue_
NEMId getDestination() const
Definition: packetinfo.inl:70
structure defines the mac downstream packet queue entry
constexpr NEMId NEM_BROADCAST_MAC_ADDRESS
Definition: types.h:69
const std::uint8_t MAX_ACCESS_CATEGORIES
Definition: macconfig.h:63
size_t getDepth()
get the number of entries for all active queues
StatisticNumeric< std::uint32_t > * pNumBroadcastPacketsTooLarge_
std::pair< DownstreamQueueEntry, bool > dequeue()
blocking dequeue, returns highest priority item first
void setMaxEntrySize(size_t)
set the max entry size for all queues
The StatisticRegistrar allows NEM layers to register statistics and statistic tables. Statistics and Statistic tables are owned by the emulator framework and a borrowed reference is returned to the registering NEM layer.
std::uint16_t NEMId
Definition: types.h:52
StatisticNumeric< T > * registerNumeric(const std::string &sName, const StatisticProperties &properties=StatisticProperties::NONE, const std::string &sDescription="")
Defines an access category container.
void registerStatistics(StatisticRegistrar &statisticRegistrar)
std::vector< DownstreamQueueEntry > enqueue(DownstreamQueueEntry &entry)
enqueue, inserts items by priority, signals on success.
void setMaxCapacity(size_t)
set the max number of entries for all queues
size_t getMaxCapacity()
get the max number of entries for all queues
void setCategories(std::uint8_t u8Category)
set the number of categories (queues)
void registerStatistics(StatisticRegistrar &statisticRegistrar)