OLD | NEW |
(Empty) | |
| 1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2009 MIRKO BANCHI |
| 4 * |
| 5 * This program is free software; you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 2 as· |
| 7 * published by the Free Software Foundation; |
| 8 * |
| 9 * This program is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 14 * You should have received a copy of the GNU General Public License |
| 15 * along with this program; if not, write to the Free Software |
| 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 * |
| 18 * Author: Mirko Banchi <mk.banchi@gmail.com> |
| 19 */ |
| 20 #include "ns3/log.h" |
| 21 #include "ns3/assert.h" |
| 22 #include "ns3/simulator.h" |
| 23 #include "ns3/fatal-error.h" |
| 24 |
| 25 #include "block-ack-manager.h" |
| 26 #include "mgt-headers.h" |
| 27 #include "ctrl-headers.h" |
| 28 #include "wifi-mac-header.h" |
| 29 #include "edca-txop-n.h" |
| 30 #include "mac-low.h" |
| 31 #include "wifi-mac-queue.h" |
| 32 #include "mac-tx-middle.h" |
| 33 |
| 34 NS_LOG_COMPONENT_DEFINE ("BlockAckManager"); |
| 35 |
| 36 namespace ns3 { |
| 37 |
| 38 BlockAckManager::Item::Item () |
| 39 {} |
| 40 |
| 41 BlockAckManager::Item::Item (Ptr<const Packet> packet, const WifiMacHeader &hdr,
Time tStamp) |
| 42 : packet (packet), hdr (hdr), timestamp (tStamp) |
| 43 {} |
| 44 |
| 45 Bar::Bar () |
| 46 {} |
| 47 |
| 48 Bar::Bar (Ptr<const Packet> bar, Mac48Address recipient, uint8_t tid, bool immed
iate) |
| 49 : bar (bar), recipient (recipient), tid (tid), immediate (immediate) |
| 50 {} |
| 51 |
| 52 BlockAckManager::BlockAckManager () |
| 53 {} |
| 54 |
| 55 BlockAckManager::~BlockAckManager () |
| 56 { |
| 57 m_queue = 0; |
| 58 m_agreements.clear (); |
| 59 m_retryPackets.clear (); |
| 60 } |
| 61 |
| 62 bool |
| 63 BlockAckManager::ExistsAgreement (Mac48Address recipient, uint8_t tid) const |
| 64 { |
| 65 return (m_agreements.find (std::make_pair (recipient, tid)) != m_agreements.en
d ()); |
| 66 } |
| 67 |
| 68 bool |
| 69 BlockAckManager::ExistsAgreementInState (Mac48Address recipient, uint8_t tid,· |
| 70 enum OriginatorBlockAckAgreement::State
state) const |
| 71 { |
| 72 AgreementsCI it; |
| 73 it = m_agreements.find (std::make_pair (recipient, tid)); |
| 74 if (it != m_agreements.end ()) |
| 75 { |
| 76 switch (state) { |
| 77 case OriginatorBlockAckAgreement::INACTIVE: |
| 78 return it->second.first.IsInactive (); |
| 79 case OriginatorBlockAckAgreement::ESTABLISHED: |
| 80 return it->second.first.IsEstablished (); |
| 81 case OriginatorBlockAckAgreement::PENDING: |
| 82 return it->second.first.IsPending (); |
| 83 case OriginatorBlockAckAgreement::UNSUCCESSFUL: |
| 84 return it->second.first.IsUnsuccessful (); |
| 85 default: |
| 86 NS_FATAL_ERROR ("Invalid state for block ack agreement"); |
| 87 } |
| 88 } |
| 89 return false; |
| 90 } |
| 91 |
| 92 void |
| 93 BlockAckManager::CreateAgreement (const MgtAddBaRequestHeader *reqHdr, Mac48Addr
ess recipient) |
| 94 { |
| 95 pair<Mac48Address, uint8_t> key (recipient, reqHdr->GetTid ()); |
| 96 OriginatorBlockAckAgreement agreement (recipient, reqHdr->GetTid ()); |
| 97 agreement.SetStartingSequence (reqHdr->GetStartingSequence ()); |
| 98 /* for now we assume that originator doesn't use this field. Use of this field······· |
| 99 is mandatory only for recipient */ |
| 100 agreement.SetBufferSize (0); |
| 101 agreement.SetTimeout (reqHdr->GetTimeout ()); |
| 102 agreement.SetAmsduSupport (reqHdr->IsAmsduSupported ()); |
| 103 if (reqHdr->IsImmediateBlockAck ()) |
| 104 { |
| 105 agreement.SetImmediateBlockAck (); |
| 106 }························· |
| 107 else |
| 108 { |
| 109 agreement.SetDelayedBlockAck (); |
| 110 } |
| 111 agreement.SetState (OriginatorBlockAckAgreement::PENDING); |
| 112 PacketQueue queue(0); |
| 113 pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue); |
| 114 m_agreements.insert (make_pair (key, value)); |
| 115 m_blockPackets (recipient, reqHdr->GetTid ()); |
| 116 } |
| 117 |
| 118 void |
| 119 BlockAckManager::DestroyAgreement (Mac48Address recipient, uint8_t tid) |
| 120 { |
| 121 AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 122 if (it != m_agreements.end ()) |
| 123 { |
| 124 for (list<PacketQueueI>::iterator i = m_retryPackets.begin (); i != m_retr
yPackets.end ();) |
| 125 { |
| 126 if ((*i)->hdr.GetAddr1 () == recipient && (*i)->hdr.GetQosTid () == ti
d) |
| 127 { |
| 128 i = m_retryPackets.erase (i); |
| 129 } |
| 130 else |
| 131 { |
| 132 i++; |
| 133 } |
| 134 } |
| 135 m_agreements.erase (it); |
| 136 //remove scheduled bar |
| 137 for (list<Bar>::iterator i = m_bars.begin (); i != m_bars.end ();) |
| 138 { |
| 139 if (i->recipient == recipient && i->tid == tid) |
| 140 { |
| 141 i = m_bars.erase (i); |
| 142 } |
| 143 else |
| 144 { |
| 145 i++; |
| 146 } |
| 147 } |
| 148 } |
| 149 } |
| 150 |
| 151 void |
| 152 BlockAckManager::UpdateAgreement (const MgtAddBaResponseHeader *respHdr, Mac48Ad
dress recipient) |
| 153 { |
| 154 uint8_t tid = respHdr->GetTid (); |
| 155 AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 156 if (it != m_agreements.end ()) |
| 157 { |
| 158 OriginatorBlockAckAgreement& agreement = it->second.first; |
| 159 agreement.SetBufferSize (respHdr->GetBufferSize () + 1); |
| 160 agreement.SetTimeout (respHdr->GetTimeout ()); |
| 161 agreement.SetAmsduSupport (respHdr->IsAmsduSupported ()); |
| 162 if (respHdr->IsImmediateBlockAck ()) |
| 163 { |
| 164 agreement.SetImmediateBlockAck (); |
| 165 }························· |
| 166 else |
| 167 { |
| 168 agreement.SetDelayedBlockAck (); |
| 169 } |
| 170 agreement.SetState (OriginatorBlockAckAgreement::ESTABLISHED); |
| 171 if (agreement.GetTimeout () != 0) |
| 172 { |
| 173 Time timeout = MicroSeconds (1024 * agreement.GetTimeout ()); |
| 174 agreement.m_inactivityEvent = Simulator::Schedule (timeout,· |
| 175 &BlockAckManager::I
nactivityTimeout,· |
| 176 this, |
| 177 recipient, tid); |
| 178 } |
| 179 } |
| 180 m_unblockPackets (recipient, tid); |
| 181 } |
| 182 |
| 183 void |
| 184 BlockAckManager::StorePacket (Ptr<const Packet> packet, const WifiMacHeader &hdr
, Time tStamp) |
| 185 { |
| 186 NS_LOG_FUNCTION (this); |
| 187 NS_ASSERT (hdr.IsQosData ()); |
| 188 |
| 189 uint8_t tid = hdr.GetQosTid (); |
| 190 Mac48Address recipient = hdr.GetAddr1 (); |
| 191 |
| 192 Item item (packet, hdr, tStamp); |
| 193 AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 194 NS_ASSERT (it != m_agreements.end ()); |
| 195 it->second.second.push_back (item); |
| 196 } |
| 197 |
| 198 Ptr<const Packet> |
| 199 BlockAckManager::GetNextPacket (WifiMacHeader &hdr) |
| 200 { |
| 201 NS_LOG_FUNCTION (this); |
| 202 Ptr<const Packet> packet = 0; |
| 203 if (m_retryPackets.size () > 0) |
| 204 { |
| 205 CleanupBuffers (); |
| 206 PacketQueueI queueIt = m_retryPackets.front (); |
| 207 m_retryPackets.pop_front (); |
| 208 packet = queueIt->packet; |
| 209 hdr = queueIt->hdr; |
| 210 hdr.SetRetry (); |
| 211 NS_LOG_INFO ("Retry packet seq="<<hdr.GetSequenceNumber ()); |
| 212 uint8_t tid = hdr.GetQosTid (); |
| 213 Mac48Address recipient = hdr.GetAddr1 (); |
| 214 |
| 215 if (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::E
STABLISHED) || |
| 216 SwitchToBlockAckIfNeeded (recipient, tid, hdr.GetSequenceNumber ())) |
| 217 { |
| 218 hdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK); |
| 219 } |
| 220 else |
| 221 { |
| 222 /* From section 9.10.3 in IEEE802.11e standard: |
| 223 * In order to improve efficiency, originators using the Block Ack fac
ility |
| 224 * may send MPDU frames with the Ack Policy subfield in QoS control fr
ames |
| 225 * set to Normal Ack if only a few MPDUs are available for transmissio
n.[...] |
| 226 * When there are sufficient number of MPDUs, the originator may switc
h back to· |
| 227 * the use of Block Ack. |
| 228 */ |
| 229 hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); |
| 230 AgreementsI i = m_agreements.find (std::make_pair (recipient, tid)); |
| 231 i->second.second.erase (queueIt); |
| 232 } |
| 233 } |
| 234 return packet; |
| 235 } |
| 236 |
| 237 bool |
| 238 BlockAckManager::HasBar (struct Bar &bar) |
| 239 { |
| 240 if (m_bars.size () > 0) |
| 241 { |
| 242 bar = m_bars.front (); |
| 243 m_bars.pop_front (); |
| 244 return true; |
| 245 } |
| 246 return false; |
| 247 } |
| 248 |
| 249 bool |
| 250 BlockAckManager::HasPackets (void) const |
| 251 { |
| 252 return (m_retryPackets.size () > 0 || m_bars.size () > 0); |
| 253 } |
| 254 |
| 255 uint32_t |
| 256 BlockAckManager::GetNBufferedPackets (Mac48Address recipient, uint8_t tid) const |
| 257 { |
| 258 uint32_t nPackets = 0; |
| 259 if (ExistsAgreement (recipient, tid)) |
| 260 { |
| 261 AgreementsCI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 262 PacketQueueCI queueIt = (*it).second.second.begin (); |
| 263 uint16_t currentSeq = 0; |
| 264 while (queueIt != (*it).second.second.end ()) |
| 265 { |
| 266 currentSeq = (*queueIt).hdr.GetSequenceNumber (); |
| 267 nPackets++; |
| 268 /* a fragmented packet must be counted as one packet */ |
| 269 while (queueIt != (*it).second.second.end () && (*queueIt).hdr.GetSequ
enceNumber () == currentSeq) |
| 270 { |
| 271 queueIt++; |
| 272 } |
| 273 } |
| 274 return nPackets; |
| 275 } |
| 276 return 0; |
| 277 } |
| 278 |
| 279 uint32_t |
| 280 BlockAckManager::GetNRetryNeededPackets (Mac48Address recipient, uint8_t tid) co
nst |
| 281 { |
| 282 uint32_t nPackets = 0; |
| 283 uint16_t currentSeq = 0; |
| 284 if (ExistsAgreement (recipient, tid)) |
| 285 { |
| 286 list<PacketQueueI>::const_iterator it = m_retryPackets.begin (); |
| 287 while (it != m_retryPackets.end ()) |
| 288 { |
| 289 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () ==
tid) |
| 290 { |
| 291 currentSeq = (*it)->hdr.GetSequenceNumber (); |
| 292 nPackets++; |
| 293 /* a fragmented packet must be counted as one packet */ |
| 294 while (it != m_retryPackets.end () && (*it)->hdr.GetSequenceNumber
() == currentSeq) |
| 295 { |
| 296 it++; |
| 297 } |
| 298 } |
| 299 } |
| 300 } |
| 301 return nPackets; |
| 302 } |
| 303 |
| 304 void |
| 305 BlockAckManager::SetBlockAckThreshold (uint8_t nPackets) |
| 306 { |
| 307 m_blockAckThreshold = nPackets; |
| 308 } |
| 309 |
| 310 void |
| 311 BlockAckManager::NotifyGotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac4
8Address recipient) |
| 312 { |
| 313 NS_LOG_FUNCTION (this); |
| 314 uint16_t sequenceFirstLost = 0; |
| 315 if (!blockAck->IsMultiTid ()) |
| 316 { |
| 317 uint8_t tid = blockAck->GetTidInfo (); |
| 318 if (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::E
STABLISHED)) |
| 319 { |
| 320 bool foundFirstLost = false; |
| 321 AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 322 PacketQueueI queueEnd = it->second.second.end (); |
| 323 |
| 324 if (it->second.first.m_inactivityEvent.IsRunning ()) |
| 325 { |
| 326 /* Upon reception of a block ack frame, the inactivity timer at th
e· |
| 327 originator must be reset.· |
| 328 For more details see section 11.5.3 in IEEE802.11e standard */ |
| 329 it->second.first.m_inactivityEvent.Cancel (); |
| 330 Time timeout = MicroSeconds (1024 * it->second.first.GetTimeout ()
); |
| 331 it->second.first.m_inactivityEvent = Simulator::Schedule (timeout, |
| 332 &BlockAc
kManager::InactivityTimeout,· |
| 333 this, |
| 334 recipien
t, tid); |
| 335 } |
| 336 if (blockAck->IsBasic ()) |
| 337 { |
| 338 for (PacketQueueI queueIt = it->second.second.begin (); queueIt !=
queueEnd;) |
| 339 { |
| 340 if (blockAck->IsFragmentReceived ((*queueIt).hdr.GetSequenceNu
mber (), |
| 341 (*queueIt).hdr.GetFragmentNu
mber ())) |
| 342 { |
| 343 queueIt = it->second.second.erase (queueIt); |
| 344 } |
| 345 else |
| 346 { |
| 347 if (!foundFirstLost) |
| 348 { |
| 349 foundFirstLost = true; |
| 350 sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber (
); |
| 351 (*it).second.first.SetStartingSequence (sequenceFirstL
ost); |
| 352 } |
| 353 m_retryPackets.push_back (queueIt); |
| 354 queueIt++; |
| 355 } |
| 356 } |
| 357 } |
| 358 else if (blockAck->IsCompressed ()) |
| 359 { |
| 360 for (PacketQueueI queueIt = it->second.second.begin (); queueIt !=
queueEnd;) |
| 361 { |
| 362 if (blockAck->IsPacketReceived ((*queueIt).hdr.GetSequenceNumb
er ())) |
| 363 { |
| 364 uint16_t currentSeq = (*queueIt).hdr.GetSequenceNumber (); |
| 365 while (queueIt != queueEnd && |
| 366 (*queueIt).hdr.GetSequenceNumber () == currentSeq) |
| 367 { |
| 368 queueIt = it->second.second.erase (queueIt); |
| 369 } |
| 370 } |
| 371 else |
| 372 { |
| 373 if (!foundFirstLost) |
| 374 { |
| 375 foundFirstLost = true; |
| 376 sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber (
); |
| 377 (*it).second.first.SetStartingSequence (sequenceFirstL
ost); |
| 378 } |
| 379 m_retryPackets.push_back (queueIt); |
| 380 queueIt++; |
| 381 } |
| 382 } |
| 383 } |
| 384 uint16_t newSeq = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, re
cipient); |
| 385 if ((foundFirstLost && !SwitchToBlockAckIfNeeded (recipient, tid, sequ
enceFirstLost)) || |
| 386 (!foundFirstLost && !SwitchToBlockAckIfNeeded (recipient, tid, new
Seq))) |
| 387 { |
| 388 it->second.first.SetState (OriginatorBlockAckAgreement::INACTIVE); |
| 389 } |
| 390 } |
| 391 } |
| 392 else |
| 393 { |
| 394 //NOT SUPPORTED FOR NOW |
| 395 NS_FATAL_ERROR ("Multi-tid block ack is not supported."); |
| 396 } |
| 397 } |
| 398 |
| 399 void |
| 400 BlockAckManager::SetBlockAckType (enum BlockAckType bAckType) |
| 401 { |
| 402 m_blockAckType = bAckType; |
| 403 } |
| 404 |
| 405 Ptr<Packet> |
| 406 BlockAckManager::ScheduleBlockAckReqIfNeeded (Mac48Address recipient, uint8_t ti
d) |
| 407 { |
| 408 /* This method checks if a BlockAckRequest frame should be send to the recipie
nt station. |
| 409 Number of packets under block ack is specified in OriginatorBlockAckAgreeme
nt object but sometimes |
| 410 this number could be incorrect. In fact is possible that a block ack agreem
ent exists for n |
| 411 packets but some of these packets are dropped due to MSDU lifetime expirati
on. |
| 412 */ |
| 413 NS_LOG_FUNCTION (this); |
| 414 AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 415 NS_ASSERT (it != m_agreements.end ()); |
| 416 |
| 417 if ((*it).second.first.NeedBlockAckRequest () || |
| 418 (GetNRetryNeededPackets (recipient, tid) == 0 && |
| 419 m_queue->GetNPacketsByTidAndAddress (tid, WifiMacHeader::ADDR1, recipient
) == 0)) |
| 420 { |
| 421 OriginatorBlockAckAgreement &agreement = (*it).second.first; |
| 422 agreement.CompleteExchange (); |
| 423 |
| 424 CtrlBAckRequestHeader reqHdr; |
| 425 if (m_blockAckType == BASIC_BLOCK_ACK || m_blockAckType == COMPRESSED_BLOC
K_ACK) |
| 426 { |
| 427 reqHdr.SetType (m_blockAckType); |
| 428 reqHdr.SetTidInfo (agreement.GetTid ()); |
| 429 reqHdr.SetStartingSequence (agreement.GetStartingSequence ()); |
| 430 } |
| 431 else if (m_blockAckType == MULTI_TID_BLOCK_ACK) |
| 432 { |
| 433 NS_FATAL_ERROR ("Multi-tid block ack is not supported."); |
| 434 } |
| 435 else |
| 436 { |
| 437 NS_FATAL_ERROR ("Invalid block ack type."); |
| 438 } |
| 439 Ptr<Packet> bar = Create<Packet> (); |
| 440 bar->AddHeader (reqHdr); |
| 441 return bar; |
| 442 } |
| 443 return 0; |
| 444 } |
| 445 |
| 446 void |
| 447 BlockAckManager::InactivityTimeout (Mac48Address recipient, uint8_t tid) |
| 448 { |
| 449 m_blockAckInactivityTimeout (recipient, tid, true); |
| 450 } |
| 451 |
| 452 void |
| 453 BlockAckManager::NotifyAgreementEstablished (Mac48Address recipient, uint8_t tid
, uint16_t startingSeq) |
| 454 { |
| 455 NS_LOG_FUNCTION (this); |
| 456 AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 457 NS_ASSERT (it != m_agreements.end ()); |
| 458 ···· |
| 459 it->second.first.SetState (OriginatorBlockAckAgreement::ESTABLISHED); |
| 460 it->second.first.SetStartingSequence (startingSeq); |
| 461 } |
| 462 |
| 463 void |
| 464 BlockAckManager::NotifyAgreementUnsuccessful (Mac48Address recipient, uint8_t ti
d) |
| 465 { |
| 466 NS_LOG_FUNCTION (this); |
| 467 AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 468 NS_ASSERT (it != m_agreements.end ()); |
| 469 if (it != m_agreements.end ()) |
| 470 { |
| 471 it->second.first.SetState (OriginatorBlockAckAgreement::UNSUCCESSFUL); |
| 472 } |
| 473 } |
| 474 |
| 475 void |
| 476 BlockAckManager::NotifyMpduTransmission (Mac48Address recipient, uint8_t tid) |
| 477 { |
| 478 NS_LOG_FUNCTION (this); |
| 479 Ptr<Packet> bar = 0; |
| 480 AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); |
| 481 NS_ASSERT (it != m_agreements.end ()); |
| 482 it->second.first.NotifyMpduTransmission (); |
| 483 bar = ScheduleBlockAckReqIfNeeded (recipient, tid); |
| 484 if (bar != 0) |
| 485 { |
| 486 Bar request (bar, recipient, tid, it->second.first.IsImmediateBlockAck ())
; |
| 487 m_bars.push_back (request); |
| 488 } |
| 489 } |
| 490 |
| 491 void |
| 492 BlockAckManager::SetQueue (Ptr<WifiMacQueue> queue) |
| 493 { |
| 494 m_queue = queue; |
| 495 } |
| 496 |
| 497 bool |
| 498 BlockAckManager::SwitchToBlockAckIfNeeded (Mac48Address recipient, uint8_t tid,
uint16_t startingSeq) |
| 499 { |
| 500 NS_LOG_FUNCTION (this); |
| 501 NS_ASSERT (!ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreemen
t::PENDING)); |
| 502 if (!ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::UNSU
CCESSFUL) && ExistsAgreement (recipient, tid)) |
| 503 { |
| 504 uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, WifiMacHeader
::ADDR1, recipient) + |
| 505 GetNBufferedPackets (recipient, tid); |
| 506 if (packets >= m_blockAckThreshold) |
| 507 { |
| 508 NotifyAgreementEstablished (recipient, tid, startingSeq); |
| 509 return true; |
| 510 } |
| 511 } |
| 512 return false; |
| 513 } |
| 514 |
| 515 void |
| 516 BlockAckManager::TearDownBlockAck (Mac48Address recipient, uint8_t tid) |
| 517 { |
| 518 NS_LOG_FUNCTION (this); |
| 519 DestroyAgreement (recipient, tid); |
| 520 } |
| 521 |
| 522 bool |
| 523 BlockAckManager::HasOtherFragments (uint16_t sequenceNumber) const |
| 524 { |
| 525 bool retVal = false; |
| 526 if (m_retryPackets.size () > 0) |
| 527 { |
| 528 Item next = *(m_retryPackets.front ()); |
| 529 if (next.hdr.GetSequenceNumber () == sequenceNumber) |
| 530 { |
| 531 retVal = true; |
| 532 } |
| 533 } |
| 534 return retVal; |
| 535 } |
| 536 |
| 537 uint32_t |
| 538 BlockAckManager::GetNextPacketSize (void) const |
| 539 { |
| 540 uint32_t size = 0; |
| 541 if (m_retryPackets.size () > 0) |
| 542 { |
| 543 Item next = *(m_retryPackets.front ()); |
| 544 size = next.packet->GetSize (); |
| 545 } |
| 546 return size; |
| 547 } |
| 548 |
| 549 void |
| 550 BlockAckManager::CleanupBuffers (void) |
| 551 { |
| 552 for (AgreementsI j = m_agreements.begin(); j != m_agreements.end (); j++) |
| 553 { |
| 554 if (j->second.second.empty ())· |
| 555 { |
| 556 continue; |
| 557 } |
| 558 Time now = Simulator::Now (); |
| 559 PacketQueueI end = j->second.second.begin (); |
| 560 for (PacketQueueI i = j->second.second.begin (); i != j->second.second.end
(); i++)· |
| 561 { |
| 562 if (i->timestamp + m_maxDelay > now)· |
| 563 { |
| 564 end = i; |
| 565 break; |
| 566 } |
| 567 else |
| 568 { |
| 569 /* remove retry packet iterator if it's present in retry queue */ |
| 570 for (list<PacketQueueI>::iterator it = m_retryPackets.begin (); it
!= m_retryPackets.end (); it++) |
| 571 { |
| 572 if ((*it)->hdr.GetAddr1 () == j->second.first.GetPeer () && |
| 573 (*it)->hdr.GetQosTid () == j->second.first.GetTid () && |
| 574 (*it)->hdr.GetSequenceNumber () == i->hdr.GetSequenceNumbe
r ()) |
| 575 { |
| 576 m_retryPackets.erase (it); |
| 577 } |
| 578 } |
| 579 } |
| 580 } |
| 581 j->second.second.erase (j->second.second.begin (), end); |
| 582 j->second.first.SetStartingSequence (end->hdr.GetSequenceNumber ()); |
| 583 } |
| 584 } |
| 585 |
| 586 void |
| 587 BlockAckManager::SetMaxPacketDelay (Time maxDelay) |
| 588 { |
| 589 NS_LOG_FUNCTION (this); |
| 590 m_maxDelay = maxDelay; |
| 591 } |
| 592 |
| 593 void |
| 594 BlockAckManager::SetBlockAckInactivityCallback (Callback<void, Mac48Address, uin
t8_t, bool> callback) |
| 595 { |
| 596 m_blockAckInactivityTimeout = callback; |
| 597 } |
| 598 |
| 599 void |
| 600 BlockAckManager::SetBlockDestinationCallback (Callback<void, Mac48Address, uint8
_t> callback) |
| 601 { |
| 602 m_blockPackets = callback; |
| 603 } |
| 604 |
| 605 void |
| 606 BlockAckManager::SetUnblockDestinationCallback (Callback<void, Mac48Address, uin
t8_t> callback) |
| 607 { |
| 608 m_unblockPackets = callback; |
| 609 } |
| 610 |
| 611 void |
| 612 BlockAckManager::SetTxMiddle (MacTxMiddle* txMiddle) |
| 613 { |
| 614 m_txMiddle = txMiddle; |
| 615 } |
| 616 |
| 617 } //namespace ns3 |
OLD | NEW |