LEFT | RIGHT |
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ | 1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
2 /* | 2 /* |
3 * Copyright (c) 2006, 2009 INRIA | 3 * Copyright (c) 2006, 2009 INRIA |
4 * Copyright (c) 2009 MIRKO BANCHI | 4 * Copyright (c) 2009 MIRKO BANCHI |
5 * | 5 * |
6 * This program is free software; you can redistribute it and/or modify | 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· | 7 * it under the terms of the GNU General Public License version 2 as· |
8 * published by the Free Software Foundation; | 8 * published by the Free Software Foundation; |
9 * | 9 * |
10 * This program is distributed in the hope that it will be useful, | 10 * This program is distributed in the hope that it will be useful, |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "edca-txop-n.h" | 25 #include "edca-txop-n.h" |
26 #include "mac-low.h" | 26 #include "mac-low.h" |
27 #include "dcf-manager.h" | 27 #include "dcf-manager.h" |
28 #include "mac-tx-middle.h" | 28 #include "mac-tx-middle.h" |
29 #include "wifi-mac-trailer.h" | 29 #include "wifi-mac-trailer.h" |
30 #include "wifi-mac.h" | 30 #include "wifi-mac.h" |
31 #include "random-stream.h" | 31 #include "random-stream.h" |
32 #include "wifi-mac-queue.h" | 32 #include "wifi-mac-queue.h" |
33 #include "msdu-aggregator.h" | 33 #include "msdu-aggregator.h" |
34 #include "mgt-headers.h" | 34 #include "mgt-headers.h" |
| 35 #include "qos-blocked-destinations.h" |
35 #include "block-ack-manager.h" | 36 #include "block-ack-manager.h" |
36 | 37 |
37 NS_LOG_COMPONENT_DEFINE ("EdcaTxopN"); | 38 NS_LOG_COMPONENT_DEFINE ("EdcaTxopN"); |
38 | 39 |
39 #define MY_DEBUG(x) \ | 40 #define MY_DEBUG(x) \ |
40 NS_LOG_DEBUG (m_low->GetAddress () << " " << x) | 41 NS_LOG_DEBUG (m_low->GetAddress () << " " << x) |
41 | 42 |
42 namespace ns3 { | 43 namespace ns3 { |
43 | 44 |
44 class EdcaTxopN::Dcf : public DcfState | 45 class EdcaTxopN::Dcf : public DcfState |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 } | 78 } |
78 virtual void MissedCts (void) { | 79 virtual void MissedCts (void) { |
79 m_txop->MissedCts (); | 80 m_txop->MissedCts (); |
80 } | 81 } |
81 virtual void GotAck (double snr, WifiMode txMode) { | 82 virtual void GotAck (double snr, WifiMode txMode) { |
82 m_txop->GotAck (snr, txMode); | 83 m_txop->GotAck (snr, txMode); |
83 } | 84 } |
84 virtual void MissedAck (void) { | 85 virtual void MissedAck (void) { |
85 m_txop->MissedAck (); | 86 m_txop->MissedAck (); |
86 } | 87 } |
87 virtual void GotBlockAck (CtrlBAckResponseHeader const *blockAck, Mac48Address
source) { | 88 virtual void GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address
source) { |
88 m_txop->GotBlockAck (blockAck, source); | 89 m_txop->GotBlockAck (blockAck, source); |
89 } | 90 } |
90 virtual void MissedBlockAck (void) { | 91 virtual void MissedBlockAck (void) { |
91 m_txop->MissedBlockAck (); | 92 m_txop->MissedBlockAck (); |
92 } | 93 } |
93 virtual void StartNext (void) { | 94 virtual void StartNext (void) { |
94 m_txop->StartNext (); | 95 m_txop->StartNext (); |
95 } | 96 } |
96 virtual void Cancel (void) { | 97 virtual void Cancel (void) { |
97 m_txop->Cancel (); | 98 m_txop->Cancel (); |
| 99 } |
| 100 |
| 101 private: |
| 102 EdcaTxopN *m_txop; |
| 103 }; |
| 104 |
| 105 class EdcaTxopN::BlockAckEventListener : public MacLowBlockAckEventListener |
| 106 { |
| 107 public: |
| 108 BlockAckEventListener (EdcaTxopN *txop) |
| 109 : MacLowBlockAckEventListener (), |
| 110 m_txop (txop) {} |
| 111 virtual ~BlockAckEventListener () {} |
| 112 |
| 113 virtual void BlockAckInactivityTimeout (Mac48Address address, uint8_t tid) { |
| 114 m_txop->SendDelbaFrame (address, tid, false); |
98 } | 115 } |
99 | 116 |
100 private: | 117 private: |
101 EdcaTxopN *m_txop; | 118 EdcaTxopN *m_txop; |
102 }; | 119 }; |
103 | 120 |
104 NS_OBJECT_ENSURE_REGISTERED (EdcaTxopN); | 121 NS_OBJECT_ENSURE_REGISTERED (EdcaTxopN); |
105 | 122 |
106 TypeId | 123 TypeId |
107 EdcaTxopN::GetTypeId (void) | 124 EdcaTxopN::GetTypeId (void) |
(...skipping 19 matching lines...) Expand all Loading... |
127 } | 144 } |
128 | 145 |
129 EdcaTxopN::EdcaTxopN () | 146 EdcaTxopN::EdcaTxopN () |
130 : m_manager (0), | 147 : m_manager (0), |
131 m_currentPacket(0), | 148 m_currentPacket(0), |
132 m_aggregator (0), | 149 m_aggregator (0), |
133 m_blockAckType (COMPRESSED_BLOCK_ACK) | 150 m_blockAckType (COMPRESSED_BLOCK_ACK) |
134 { | 151 { |
135 NS_LOG_FUNCTION (this); | 152 NS_LOG_FUNCTION (this); |
136 m_transmissionListener = new EdcaTxopN::TransmissionListener (this); | 153 m_transmissionListener = new EdcaTxopN::TransmissionListener (this); |
| 154 m_blockAckListener = new EdcaTxopN::BlockAckEventListener (this); |
137 m_dcf = new EdcaTxopN::Dcf (this); | 155 m_dcf = new EdcaTxopN::Dcf (this); |
138 m_queue = CreateObject<WifiMacQueue> (); | 156 m_queue = CreateObject<WifiMacQueue> (); |
139 m_rng = new RealRandomStream (); | 157 m_rng = new RealRandomStream (); |
| 158 m_qosBlockedDestinations = new QosBlockedDestinations (); |
140 m_baManager = new BlockAckManager (); | 159 m_baManager = new BlockAckManager (); |
141 m_baManager->SetQueue (m_queue); | 160 m_baManager->SetQueue (m_queue); |
142 m_baManager->SetBlockAckType (m_blockAckType); | 161 m_baManager->SetBlockAckType (m_blockAckType); |
143 m_queue->SetBlockAckManager (m_baManager); | 162 m_baManager->SetBlockDestinationCallback (MakeCallback (&QosBlockedDestination
s::Block, m_qosBlockedDestinations)); |
| 163 m_baManager->SetUnblockDestinationCallback (MakeCallback (&QosBlockedDestinati
ons::Unblock, m_qosBlockedDestinations)); |
| 164 m_baManager->SetMaxPacketDelay (m_queue->GetMaxDelay ()); |
144 } | 165 } |
145 | 166 |
146 EdcaTxopN::~EdcaTxopN () | 167 EdcaTxopN::~EdcaTxopN () |
147 { | 168 { |
148 NS_LOG_FUNCTION (this); | 169 NS_LOG_FUNCTION (this); |
149 } | 170 } |
150 | 171 |
151 void | 172 void |
152 EdcaTxopN::DoDispose (void) | 173 EdcaTxopN::DoDispose (void) |
153 { | 174 { |
154 NS_LOG_FUNCTION (this); | 175 NS_LOG_FUNCTION (this); |
155 m_queue = 0; | 176 m_queue = 0; |
156 m_low = 0; | 177 m_low = 0; |
157 m_stationManager = 0; | 178 m_stationManager = 0; |
158 delete m_transmissionListener; | 179 delete m_transmissionListener; |
159 delete m_dcf; | 180 delete m_dcf; |
160 delete m_rng; | 181 delete m_rng; |
| 182 delete m_qosBlockedDestinations; |
161 delete m_baManager; | 183 delete m_baManager; |
| 184 delete m_blockAckListener; |
162 m_transmissionListener = 0; | 185 m_transmissionListener = 0; |
163 m_dcf = 0; | 186 m_dcf = 0; |
164 m_rng = 0; | 187 m_rng = 0; |
| 188 m_qosBlockedDestinations = 0; |
165 m_baManager = 0; | 189 m_baManager = 0; |
| 190 m_blockAckListener = 0; |
166 m_txMiddle = 0; | 191 m_txMiddle = 0; |
167 m_aggregator = 0; | 192 m_aggregator = 0; |
168 } | 193 } |
169 | 194 |
170 void | 195 void |
171 EdcaTxopN::SetManager (DcfManager *manager) | 196 EdcaTxopN::SetManager (DcfManager *manager) |
172 { | 197 { |
173 NS_LOG_FUNCTION (this << manager); | 198 NS_LOG_FUNCTION (this << manager); |
174 m_manager = manager; | 199 m_manager = manager; |
175 m_manager->Add (m_dcf); | 200 m_manager->Add (m_dcf); |
(...skipping 23 matching lines...) Expand all Loading... |
199 NS_LOG_FUNCTION (this << type); | 224 NS_LOG_FUNCTION (this << type); |
200 m_typeOfStation = type; | 225 m_typeOfStation = type; |
201 } | 226 } |
202 | 227 |
203 enum TypeOfStation | 228 enum TypeOfStation |
204 EdcaTxopN::GetTypeOfStation (void) const | 229 EdcaTxopN::GetTypeOfStation (void) const |
205 { | 230 { |
206 return m_typeOfStation; | 231 return m_typeOfStation; |
207 } | 232 } |
208 | 233 |
209 const MacTxMiddle* | |
210 EdcaTxopN::GetTxMiddle (void) const | |
211 { | |
212 return m_txMiddle; | |
213 } | |
214 | |
215 void· | 234 void· |
216 EdcaTxopN::SetMaxQueueSize (uint32_t size) | 235 EdcaTxopN::SetMaxQueueSize (uint32_t size) |
217 { | 236 { |
218 NS_LOG_FUNCTION (this << size); | 237 NS_LOG_FUNCTION (this << size); |
219 m_queue->SetMaxSize (size); | 238 m_queue->SetMaxSize (size); |
220 } | 239 } |
221 | 240 |
222 void | 241 void |
223 EdcaTxopN::SetMaxQueueDelay (Time delay) | 242 EdcaTxopN::SetMaxQueueDelay (Time delay) |
224 { | 243 { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 { | 308 { |
290 return !m_queue->IsEmpty () || m_currentPacket != 0 || m_baManager->HasPackets
(); | 309 return !m_queue->IsEmpty () || m_currentPacket != 0 || m_baManager->HasPackets
(); |
291 } | 310 } |
292 | 311 |
293 void | 312 void |
294 EdcaTxopN::NotifyAccessGranted (void) | 313 EdcaTxopN::NotifyAccessGranted (void) |
295 { | 314 { |
296 NS_LOG_FUNCTION (this); | 315 NS_LOG_FUNCTION (this); |
297 if (m_currentPacket == 0) | 316 if (m_currentPacket == 0) |
298 { | 317 { |
299 if (m_blockAckThreshold > 0 && | |
300 m_baManager->IsBlockAckReqNeeded ()) | |
301 { | |
302 SendBlockAckRequest (); | |
303 return; | |
304 } | |
305 if (m_queue->IsEmpty () && !m_baManager->HasPackets ()) | 318 if (m_queue->IsEmpty () && !m_baManager->HasPackets ()) |
306 { | 319 { |
307 MY_DEBUG ("queue is empty"); | 320 MY_DEBUG ("queue is empty"); |
308 return;· | 321 return;· |
| 322 } |
| 323 struct Bar bar; |
| 324 if (m_baManager->HasBar (bar)) |
| 325 { |
| 326 SendBlockAckRequest (bar); |
| 327 return; |
309 } | 328 } |
310 /* check if packets need retransmission are stored in BlockAckManager */ | 329 /* check if packets need retransmission are stored in BlockAckManager */ |
311 m_currentPacket = m_baManager->GetNextPacket (m_currentHdr); | 330 m_currentPacket = m_baManager->GetNextPacket (m_currentHdr); |
312 if (m_currentPacket == 0) | 331 if (m_currentPacket == 0) |
313 { | 332 { |
314 if (m_queue->PeekFirstAvailable (&m_currentHdr, m_currentPacketTimesta
mp) == 0) | 333 if (m_queue->PeekFirstAvailable (&m_currentHdr, m_currentPacketTimesta
mp, m_qosBlockedDestinations) == 0) |
315 { | 334 { |
316 MY_DEBUG ("no available packets in the queue"); | 335 MY_DEBUG ("no available packets in the queue"); |
317 return; | 336 return; |
318 } | 337 } |
319 if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast
() && | 338 if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast
() && |
320 m_blockAckThreshold > 0 && | 339 m_blockAckThreshold > 0 && |
321 !m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_current
Hdr.GetQosTid ()) && | 340 !m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_current
Hdr.GetQosTid ()) && |
322 SetupBlockAckIfNeeded ()) | 341 SetupBlockAckIfNeeded ()) |
323 { | 342 { |
324 return; | 343 return; |
325 } | 344 } |
326 m_currentPacket = m_queue->DequeueFirstAvailable (&m_currentHdr, m_cur
rentPacketTimestamp); | 345 m_currentPacket = m_queue->DequeueFirstAvailable (&m_currentHdr, m_cur
rentPacketTimestamp, m_qosBlockedDestinations); |
327 NS_ASSERT (m_currentPacket != 0); | 346 NS_ASSERT (m_currentPacket != 0); |
| 347 ·········· |
328 uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHd
r); | 348 uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHd
r); |
329 m_currentHdr.SetSequenceNumber (sequence); | 349 m_currentHdr.SetSequenceNumber (sequence); |
330 m_currentHdr.SetFragmentNumber (0); | 350 m_currentHdr.SetFragmentNumber (0); |
331 m_currentHdr.SetNoMoreFragments (); | 351 m_currentHdr.SetNoMoreFragments (); |
332 m_currentHdr.SetNoRetry (); | 352 m_currentHdr.SetNoRetry (); |
| 353 m_fragmentNumber = 0; |
| 354 MY_DEBUG ("dequeued size="<<m_currentPacket->GetSize ()<< |
| 355 ", to="<<m_currentHdr.GetAddr1 ()<< |
| 356 ", seq="<<m_currentHdr.GetSequenceControl ()); |
333 if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast
()) | 357 if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast
()) |
334 { | 358 { |
335 VerifyBlockAck (); | 359 VerifyBlockAck (); |
336 } | 360 } |
337 m_fragmentNumber = 0; | |
338 MY_DEBUG ("dequeued size="<<m_currentPacket->GetSize ()<< | |
339 ", to="<<m_currentHdr.GetAddr1 ()<< | |
340 ", seq="<<m_currentHdr.GetSequenceControl ()); | |
341 } | 361 } |
342 } | 362 } |
343 MacLowTransmissionParameters params; | 363 MacLowTransmissionParameters params; |
344 params.DisableOverrideDurationId (); | 364 params.DisableOverrideDurationId (); |
345 if (m_currentHdr.IsBlockAckReq ()) | 365 if (m_currentHdr.GetAddr1 ().IsBroadcast ())· |
346 { | |
347 SendBlockAckRequest (); | |
348 } | |
349 else if (m_currentHdr.GetAddr1 ().IsBroadcast ())· | |
350 { | 366 { |
351 params.DisableRts (); | 367 params.DisableRts (); |
352 params.DisableAck (); | 368 params.DisableAck (); |
353 params.DisableNextData (); | 369 params.DisableNextData (); |
354 m_low->StartTransmission (m_currentPacket, | 370 m_low->StartTransmission (m_currentPacket, |
355 &m_currentHdr, | 371 &m_currentHdr, |
356 params, | 372 params, |
357 m_transmissionListener); | 373 m_transmissionListener); |
358 ······ | 374 ······ |
359 m_currentPacket = 0; | 375 m_currentPacket = 0; |
360 m_dcf->ResetCw (); | 376 m_dcf->ResetCw (); |
361 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); | 377 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); |
362 StartAccessIfNeeded (); | 378 StartAccessIfNeeded (); |
363 MY_DEBUG ("tx broadcast"); | 379 MY_DEBUG ("tx broadcast"); |
364 } | 380 } |
365 else | 381 else |
366 { | 382 { |
367 if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ()) | 383 if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ()) |
368 { | 384 { |
369 params.DisableAck (); | 385 params.DisableAck (); |
370 } | 386 } |
371 else | 387 else |
372 { | 388 { |
373 params.EnableAck (); | 389 params.EnableAck (); |
374 } | 390 } |
375 if (NeedFragmentation () && ((m_currentHdr.IsQosData () &&· | 391 if (NeedFragmentation () && ((m_currentHdr.IsQosData () &&· |
376 !m_currentHdr.IsQosAmsdu ()) || | 392 !m_currentHdr.IsQosAmsdu ()) || |
377 m_currentHdr.IsData ()) && m_blockAckThreshol
d == 0 && | 393 m_currentHdr.IsData ()) && |
378 m_blockAckType ==
COMPRESSED_BLOCK_ACK) | 394 (m_blockAckThreshold == 0 || |
| 395 m_blockAckType == BASIC_BLOCK_ACK)) |
379 { | 396 { |
380 //With COMPRESSED_BLOCK_ACK fragmentation must be avoided. | 397 //With COMPRESSED_BLOCK_ACK fragmentation must be avoided. |
381 params.DisableRts (); | 398 params.DisableRts (); |
382 WifiMacHeader hdr; | 399 WifiMacHeader hdr; |
383 Ptr<Packet> fragment = GetFragmentPacket (&hdr); | 400 Ptr<Packet> fragment = GetFragmentPacket (&hdr); |
384 if (IsLastFragment ())· | 401 if (IsLastFragment ())· |
385 { | 402 { |
386 MY_DEBUG ("fragmenting last fragment size=" << fragment->GetSize (
)); | 403 MY_DEBUG ("fragmenting last fragment size=" << fragment->GetSize (
)); |
387 params.DisableNextData (); | 404 params.DisableNextData (); |
388 }· | 405 }· |
389 else· | 406 else· |
390 { | 407 { |
391 MY_DEBUG ("fragmenting size=" << fragment->GetSize ()); | 408 MY_DEBUG ("fragmenting size=" << fragment->GetSize ()); |
392 params.EnableNextData (GetNextFragmentSize ()); | 409 params.EnableNextData (GetNextFragmentSize ()); |
393 } | 410 } |
394 m_low->StartTransmission (fragment, &hdr, params,· | 411 m_low->StartTransmission (fragment, &hdr, params,· |
395 m_transmissionListener); | 412 m_transmissionListener); |
396 if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ()) | |
397 { | |
398 m_baManager->StorePacket (fragment, hdr, m_currentPacketTimestamp)
; | |
399 } | |
400 } | 413 } |
401 else | 414 else |
402 { | 415 { |
403 WifiMacHeader peekedHdr; | 416 WifiMacHeader peekedHdr; |
404 if (m_currentHdr.IsQosData () && | 417 if (m_currentHdr.IsQosData () && |
405 m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (
),· | 418 m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (
),· |
406 WifiMacHeader::ADDR1, m_currentHdr.G
etAddr1 ()) && | 419 WifiMacHeader::ADDR1, m_currentHdr.G
etAddr1 ()) && |
407 !m_currentHdr.GetAddr1 ().IsBroadcast () && | 420 !m_currentHdr.GetAddr1 ().IsBroadcast () && |
408 m_aggregator != 0 && !m_currentHdr.IsRetry ()) | 421 m_aggregator != 0 && !m_currentHdr.IsRetry ()) |
409 { | 422 { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 } | 522 } |
510 | 523 |
511 void· | 524 void· |
512 EdcaTxopN::NotifyChannelSwitching (void) | 525 EdcaTxopN::NotifyChannelSwitching (void) |
513 { | 526 { |
514 m_queue->Flush(); | 527 m_queue->Flush(); |
515 m_currentPacket = 0; | 528 m_currentPacket = 0; |
516 } | 529 } |
517 | 530 |
518 void | 531 void |
519 EdcaTxopN::Queue (Ptr<const Packet> packet, WifiMacHeader const &hdr) | 532 EdcaTxopN::Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr) |
520 { | 533 { |
521 NS_LOG_FUNCTION (this << packet << &hdr); | 534 NS_LOG_FUNCTION (this << packet << &hdr); |
522 WifiMacTrailer fcs; | 535 WifiMacTrailer fcs; |
523 uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.
GetSerializedSize (); | 536 uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.
GetSerializedSize (); |
524 WifiRemoteStation *station = GetStation (hdr.GetAddr1 ()); | 537 WifiRemoteStation *station = GetStation (hdr.GetAddr1 ()); |
525 station->PrepareForQueue (packet, fullPacketSize); | 538 station->PrepareForQueue (packet, fullPacketSize); |
526 m_queue->Enqueue (packet, hdr); | 539 m_queue->Enqueue (packet, hdr); |
527 StartAccessIfNeeded (); | 540 StartAccessIfNeeded (); |
528 } | 541 } |
529 | 542 |
530 void | 543 void |
531 EdcaTxopN::GotAck (double snr, WifiMode txMode) | 544 EdcaTxopN::GotAck (double snr, WifiMode txMode) |
532 { | 545 { |
533 NS_LOG_FUNCTION (this << snr << txMode); | 546 NS_LOG_FUNCTION (this << snr << txMode); |
534 if (!NeedFragmentation () || | 547 if (!NeedFragmentation () || |
535 IsLastFragment () || | 548 IsLastFragment () || |
536 m_currentHdr.IsQosAmsdu ())· | 549 m_currentHdr.IsQosAmsdu ())· |
537 { | 550 { |
538 MY_DEBUG ("got ack. tx done."); | 551 MY_DEBUG ("got ack. tx done."); |
539 if (!m_txOkCallback.IsNull ()) | 552 if (!m_txOkCallback.IsNull ()) |
540 { | 553 { |
541 m_txOkCallback (m_currentHdr); | 554 m_txOkCallback (m_currentHdr); |
542 } | 555 } |
543 ······ | 556 ······ |
544 if (m_currentHdr.IsAction ()) | 557 if (m_currentHdr.IsAction ()) |
545 { | 558 { |
546 MgtActionFrameHeader actHdr; | 559 WifiActionHeader actionHdr; |
547 m_currentPacket->PeekHeader (actHdr); | 560 Ptr<Packet> p = m_currentPacket->Copy (); |
548 if (actHdr.IsDelBa ()) | 561 p->RemoveHeader (actionHdr); |
| 562 if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK && |
| 563 actionHdr.GetAction ().blockAck == WifiActionHeader::BLOCK_ACK_DEL
BA) |
549 { | 564 { |
550 MgtDelBaHeader delBa; | 565 MgtDelBaHeader delBa; |
551 m_currentPacket->PeekHeader (delBa); | 566 p->PeekHeader (delBa); |
552 if (delBa.IsByOriginator ()) | 567 if (delBa.IsByOriginator ()) |
553 { | 568 { |
554 m_baManager->TearDownBlockAck (m_currentHdr.GetAddr1 (), delBa
.GetTid ()); | 569 m_baManager->TearDownBlockAck (m_currentHdr.GetAddr1 (), delBa
.GetTid ()); |
555 } | 570 } |
556 else | 571 else |
557 { | 572 { |
558 m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), del
Ba.GetTid ()); | 573 m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), del
Ba.GetTid ()); |
559 } | 574 } |
560 } | 575 } |
561 } | 576 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 m_dcf->UpdateFailedCw (); | 611 m_dcf->UpdateFailedCw (); |
597 } | 612 } |
598 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); | 613 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); |
599 RestartAccessIfNeeded (); | 614 RestartAccessIfNeeded (); |
600 } | 615 } |
601 | 616 |
602 void | 617 void |
603 EdcaTxopN::MissedBlockAck (void) | 618 EdcaTxopN::MissedBlockAck (void) |
604 { | 619 { |
605 NS_LOG_FUNCTION (this); | 620 NS_LOG_FUNCTION (this); |
606 MY_DEBUG ("missed block ack"); | 621 MY_DEBUG ("missed block ack"); |
607 //should i report this to station addressed by ADDR1? | 622 //should i report this to station addressed by ADDR1? |
608 MY_DEBUG ("Retransmit block ack request"); | 623 MY_DEBUG ("Retransmit block ack request"); |
609 m_currentHdr.SetRetry (); | 624 m_currentHdr.SetRetry (); |
610 m_dcf->UpdateFailedCw (); | 625 m_dcf->UpdateFailedCw (); |
611 ·· | 626 ·· |
612 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); | 627 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); |
613 RestartAccessIfNeeded (); | 628 RestartAccessIfNeeded (); |
614 } | 629 } |
615 | 630 |
616 Ptr<MsduAggregator> | 631 Ptr<MsduAggregator> |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 }· | 770 }· |
756 else· | 771 else· |
757 { | 772 { |
758 hdr->SetMoreFragments (); | 773 hdr->SetMoreFragments (); |
759 } | 774 } |
760 fragment = m_currentPacket->CreateFragment (startOffset,· | 775 fragment = m_currentPacket->CreateFragment (startOffset,· |
761 GetFragmentSize ()); | 776 GetFragmentSize ()); |
762 return fragment; | 777 return fragment; |
763 } | 778 } |
764 | 779 |
| 780 void |
| 781 EdcaTxopN::SetAccessClass (enum AccessClass ac) |
| 782 { |
| 783 m_ac = ac; |
| 784 } |
| 785 |
765 Mac48Address | 786 Mac48Address |
766 EdcaTxopN::MapSrcAddressForAggregation (WifiMacHeader const &hdr) | 787 EdcaTxopN::MapSrcAddressForAggregation (const WifiMacHeader &hdr) |
767 { | 788 { |
768 Mac48Address retval; | 789 Mac48Address retval; |
769 if (m_typeOfStation == STA || m_typeOfStation == ADHOC_STA) | 790 if (m_typeOfStation == STA || m_typeOfStation == ADHOC_STA) |
770 { | 791 { |
771 retval = hdr.GetAddr2 (); | 792 retval = hdr.GetAddr2 (); |
772 } | 793 } |
773 else | 794 else |
774 { | 795 { |
775 retval = hdr.GetAddr3 (); | 796 retval = hdr.GetAddr3 (); |
776 } | 797 } |
777 return retval; | 798 return retval; |
778 } | 799 } |
779 | 800 |
780 Mac48Address | 801 Mac48Address |
781 EdcaTxopN::MapDestAddressForAggregation (WifiMacHeader const &hdr) | 802 EdcaTxopN::MapDestAddressForAggregation (const WifiMacHeader &hdr) |
782 { | 803 { |
783 Mac48Address retval; | 804 Mac48Address retval; |
784 if (m_typeOfStation == AP || m_typeOfStation == ADHOC_STA) | 805 if (m_typeOfStation == AP || m_typeOfStation == ADHOC_STA) |
785 { | 806 { |
786 retval = hdr.GetAddr1 (); | 807 retval = hdr.GetAddr1 (); |
787 } | 808 } |
788 else | 809 else |
789 { | 810 { |
790 retval = hdr.GetAddr3 (); | 811 retval = hdr.GetAddr3 (); |
791 } | 812 } |
792 return retval; | 813 return retval; |
793 } | 814 } |
794 | 815 |
795 void | 816 void |
796 EdcaTxopN::SetMsduAggregator (Ptr<MsduAggregator> aggr) | 817 EdcaTxopN::SetMsduAggregator (Ptr<MsduAggregator> aggr) |
797 { | 818 { |
798 m_aggregator = aggr; | 819 m_aggregator = aggr; |
799 } | 820 } |
800 | 821 |
801 void | 822 void |
802 EdcaTxopN::PushFront (Ptr<const Packet> packet, WifiMacHeader const &hdr) | 823 EdcaTxopN::PushFront (Ptr<const Packet> packet, const WifiMacHeader &hdr) |
803 { | 824 { |
804 NS_LOG_FUNCTION (this << packet << &hdr); | 825 NS_LOG_FUNCTION (this << packet << &hdr); |
805 WifiMacTrailer fcs; | 826 WifiMacTrailer fcs; |
806 uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.
GetSerializedSize (); | 827 uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.
GetSerializedSize (); |
807 WifiRemoteStation *station = GetStation (hdr.GetAddr1 ()); | 828 WifiRemoteStation *station = GetStation (hdr.GetAddr1 ()); |
808 station->PrepareForQueue (packet, fullPacketSize); | 829 station->PrepareForQueue (packet, fullPacketSize); |
809 m_queue->PushFront (packet, hdr); | 830 m_queue->PushFront (packet, hdr); |
810 StartAccessIfNeeded (); | 831 StartAccessIfNeeded (); |
811 } | 832 } |
812 | 833 |
813 void | 834 void |
814 EdcaTxopN::GotAddBaResponse (MgtAddBaResponseHeader const *respHdr, Mac48Address
recipient) | 835 EdcaTxopN::GotAddBaResponse (const MgtAddBaResponseHeader *respHdr, Mac48Address
recipient) |
815 { | 836 { |
816 NS_LOG_FUNCTION (this); | 837 NS_LOG_FUNCTION (this); |
817 MY_DEBUG ("received ADDBA response from "<<recipient); | 838 MY_DEBUG ("received ADDBA response from "<<recipient); |
818 uint8_t tid = respHdr->GetTid (); | 839 uint8_t tid = respHdr->GetTid (); |
819 if (m_baManager->ExistsPendingAgreement (recipient, tid)) | 840 if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgr
eement::PENDING)) |
820 { | 841 { |
821 if (respHdr->GetStatusCode ().IsSuccess ()) | 842 if (respHdr->GetStatusCode ().IsSuccess ()) |
822 { | 843 { |
823 MY_DEBUG ("block ack agreement established with "<<recipient); | 844 MY_DEBUG ("block ack agreement established with "<<recipient); |
824 m_baManager->UpdateAgreement (respHdr, recipient); | 845 m_baManager->UpdateAgreement (respHdr, recipient); |
825 } | 846 } |
826 else | 847 else |
827 { | 848 { |
828 MY_DEBUG ("discard ADDBA response"<<recipient); | 849 MY_DEBUG ("discard ADDBA response"<<recipient); |
829 m_baManager->NotifyUnsuccessfulAgreement (recipient, tid); | 850 m_baManager->NotifyAgreementUnsuccessful (recipient, tid); |
830 } | 851 } |
831 } | 852 } |
832 RestartAccessIfNeeded (); | 853 RestartAccessIfNeeded (); |
833 } | 854 } |
834 | 855 |
835 void | 856 void |
836 EdcaTxopN::GotDelBaFrame (const MgtDelBaHeader *delBaHdr, Mac48Address recipient
) | 857 EdcaTxopN::GotDelBaFrame (const MgtDelBaHeader *delBaHdr, Mac48Address recipient
) |
837 { | 858 { |
838 NS_LOG_FUNCTION (this); | 859 NS_LOG_FUNCTION (this); |
839 MY_DEBUG ("received DELBA frame from="<<recipient); | 860 MY_DEBUG ("received DELBA frame from="<<recipient); |
840 m_baManager->TearDownBlockAck (recipient, delBaHdr->GetTid ()); | 861 m_baManager->TearDownBlockAck (recipient, delBaHdr->GetTid ()); |
841 } | 862 } |
842 | 863 |
843 void | 864 void |
844 EdcaTxopN::GotBlockAck (CtrlBAckResponseHeader const *blockAck, Mac48Address rec
ipient) | 865 EdcaTxopN::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address rec
ipient) |
845 { | 866 { |
846 MY_DEBUG ("got block ack from="<<recipient); | 867 MY_DEBUG ("got block ack from="<<recipient); |
847 m_baManager->GotBlockAck (blockAck, recipient); | 868 m_baManager->NotifyGotBlockAck (blockAck, recipient); |
848 m_currentPacket = 0; | 869 m_currentPacket = 0; |
849 m_dcf->ResetCw (); | 870 m_dcf->ResetCw (); |
850 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); | 871 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); |
851 RestartAccessIfNeeded (); | 872 RestartAccessIfNeeded (); |
852 } | 873 } |
853 | 874 |
854 void | 875 void |
855 EdcaTxopN::VerifyBlockAck (void) | 876 EdcaTxopN::VerifyBlockAck (void) |
856 { | 877 { |
857 NS_LOG_FUNCTION (this); | 878 NS_LOG_FUNCTION (this); |
858 uint8_t tid = m_currentHdr.GetQosTid (); | 879 uint8_t tid = m_currentHdr.GetQosTid (); |
859 Mac48Address recipient = m_currentHdr.GetAddr1 (); | 880 Mac48Address recipient = m_currentHdr.GetAddr1 (); |
860 uint16_t sequence = m_currentHdr.GetSequenceNumber (); | 881 uint16_t sequence = m_currentHdr.GetSequenceNumber (); |
861 if (m_baManager->ExistsInactiveAgreement (recipient, tid)) | 882 if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgr
eement::INACTIVE)) |
862 { | 883 { |
863 m_baManager->RefreshBlockAck (recipient, tid, sequence); | 884 m_baManager->SwitchToBlockAckIfNeeded (recipient, tid, sequence); |
864 } | 885 } |
865 if (m_baManager->ExistsEstablishedAgreement (recipient, tid)) | 886 if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgr
eement::ESTABLISHED)) |
866 { | 887 { |
867 m_currentHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK); | 888 m_currentHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK); |
868 } | 889 } |
869 } | 890 } |
870 | 891 |
871 void | 892 void |
872 EdcaTxopN::CompleteTx (void) | 893 EdcaTxopN::CompleteTx (void) |
873 { | 894 { |
874 if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ()) | 895 if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ()) |
875 { | 896 { |
(...skipping 22 matching lines...) Expand all Loading... |
898 { | 919 { |
899 /* Block ack setup */ | 920 /* Block ack setup */ |
900 uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (t
id, recipient); | 921 uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (t
id, recipient); |
901 SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTi
meout, true); | 922 SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTi
meout, true); |
902 return true; | 923 return true; |
903 } | 924 } |
904 return false; | 925 return false; |
905 } | 926 } |
906 | 927 |
907 void | 928 void |
908 EdcaTxopN::SendBlockAckRequest (void) | 929 EdcaTxopN::SendBlockAckRequest (const struct Bar &bar) |
909 { | 930 { |
910 NS_LOG_FUNCTION (this); | 931 NS_LOG_FUNCTION (this); |
911 bool immediate; | 932 WifiMacHeader hdr; |
912 m_baManager->GetNextBlockAckRequest (m_currentPacket, m_currentHdr, immediate)
; | 933 hdr.SetType (WIFI_MAC_CTL_BACKREQ); |
913 ·· | 934 hdr.SetAddr1 (bar.recipient); |
| 935 hdr.SetAddr2 (m_low->GetAddress ()); |
| 936 hdr.SetAddr3 (m_low->GetBssid ()); |
| 937 hdr.SetDsNotTo (); |
| 938 hdr.SetDsNotFrom (); |
| 939 hdr.SetNoRetry (); |
| 940 hdr.SetNoMoreFragments (); |
| 941 |
| 942 m_currentPacket = bar.bar; |
| 943 m_currentHdr = hdr; |
| 944 |
914 MacLowTransmissionParameters params; | 945 MacLowTransmissionParameters params; |
915 params.DisableRts (); | 946 params.DisableRts (); |
916 params.DisableNextData (); | 947 params.DisableNextData (); |
917 params.DisableOverrideDurationId (); | 948 params.DisableOverrideDurationId (); |
918 if (immediate) | 949 if (bar.immediate) |
919 { | 950 { |
920 if (m_blockAckType == BASIC_BLOCK_ACK) | 951 if (m_blockAckType == BASIC_BLOCK_ACK) |
921 { | 952 { |
922 params.EnableBasicBlockAck (); | 953 params.EnableBasicBlockAck (); |
923 } | 954 } |
924 else if (m_blockAckType == COMPRESSED_BLOCK_ACK) | 955 else if (m_blockAckType == COMPRESSED_BLOCK_ACK) |
925 { | 956 { |
926 params.EnableCompressedBlockAck (); | 957 params.EnableCompressedBlockAck (); |
927 } | 958 } |
928 else if (m_blockAckType == MULTI_TID_BLOCK_ACK) | 959 else if (m_blockAckType == MULTI_TID_BLOCK_ACK) |
929 { | 960 { |
930 //Not supported | 961 NS_FATAL_ERROR ("Multi-tid block ack is not supported"); |
931 NS_ASSERT (false); | |
932 } | 962 } |
933 } | 963 } |
934 else | 964 else |
935 { | 965 { |
| 966 //Delayed block ack |
936 params.EnableAck (); | 967 params.EnableAck (); |
937 } | 968 } |
938 m_low->StartTransmission (m_currentPacket, &m_currentHdr, params, m_transmissi
onListener); | 969 m_low->StartTransmission (m_currentPacket, &m_currentHdr, params, m_transmissi
onListener); |
939 } | 970 } |
940 | 971 |
941 void | 972 void |
942 EdcaTxopN::CompleteConfig (void) | 973 EdcaTxopN::CompleteConfig (void) |
943 { | 974 { |
944 NS_LOG_FUNCTION (this); | 975 NS_LOG_FUNCTION (this); |
945 Ptr<EdcaTxopN> edca (this); | 976 m_baManager->SetTxMiddle (m_txMiddle); |
946 m_baManager->SetEdca (edca); | 977 m_low->RegisterBlockAckListenerForAc (m_ac, m_blockAckListener); |
| 978 m_baManager->SetBlockAckInactivityCallback (MakeCallback (&EdcaTxopN::SendDelb
aFrame, this)); |
947 } | 979 } |
948 | 980 |
949 void | 981 void |
950 EdcaTxopN::SetBlockAckThreshold (uint8_t threshold) | 982 EdcaTxopN::SetBlockAckThreshold (uint8_t threshold) |
951 { | 983 { |
952 m_blockAckThreshold = threshold; | 984 m_blockAckThreshold = threshold; |
953 m_baManager->SetBlockAckThreshold (threshold); | 985 m_baManager->SetBlockAckThreshold (threshold); |
954 } | 986 } |
955 | 987 |
956 uint8_t | 988 uint8_t |
957 EdcaTxopN::GetBlockAckThreshold (void) const | 989 EdcaTxopN::GetBlockAckThreshold (void) const |
958 { | 990 { |
959 return m_blockAckThreshold; | 991 return m_blockAckThreshold; |
960 } | 992 } |
961 | 993 |
962 void | 994 void |
963 EdcaTxopN::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,· | 995 EdcaTxopN::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,· |
964 uint16_t timeout, bool immediateBAck) | 996 uint16_t timeout, bool immediateBAck) |
965 { | 997 { |
966 NS_LOG_FUNCTION (this); | 998 NS_LOG_FUNCTION (this); |
967 MY_DEBUG ("sent ADDBA request to "<<dest); | 999 MY_DEBUG ("sent ADDBA request to "<<dest); |
968 WifiMacHeader hdr; | 1000 WifiMacHeader hdr; |
969 hdr.SetAction (); | 1001 hdr.SetAction (); |
970 hdr.SetAddr1 (dest); | 1002 hdr.SetAddr1 (dest); |
971 hdr.SetAddr2 (m_low->GetAddress ()); | 1003 hdr.SetAddr2 (m_low->GetAddress ()); |
972 hdr.SetAddr3 (m_low->GetBssid ()); | 1004 hdr.SetAddr3 (m_low->GetAddress ()); |
973 hdr.SetDsNotTo (); | 1005 hdr.SetDsNotTo (); |
974 hdr.SetDsNotFrom (); | 1006 hdr.SetDsNotFrom (); |
| 1007 ·· |
| 1008 WifiActionHeader actionHdr; |
| 1009 WifiActionHeader::ActionValue action; |
| 1010 action.blockAck = WifiActionHeader::BLOCK_ACK_ADDBA_REQUEST; |
| 1011 actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action); |
| 1012 |
975 Ptr<Packet> packet = Create<Packet> (); | 1013 Ptr<Packet> packet = Create<Packet> (); |
976 /*Setting ADDBARequest header*/ | 1014 /*Setting ADDBARequest header*/ |
977 MgtAddBaRequestHeader reqHdr; | 1015 MgtAddBaRequestHeader reqHdr; |
978 reqHdr.SetAmsduSupport (true); | 1016 reqHdr.SetAmsduSupport (true); |
979 if (immediateBAck) | 1017 if (immediateBAck) |
980 { | 1018 { |
981 reqHdr.SetImmediateBlockAck (); | 1019 reqHdr.SetImmediateBlockAck (); |
982 } | 1020 } |
983 else | 1021 else |
984 { | 1022 { |
985 reqHdr.SetDelayedBlockAck (); | 1023 reqHdr.SetDelayedBlockAck (); |
986 } | 1024 } |
987 reqHdr.SetTid (tid); | 1025 reqHdr.SetTid (tid); |
988 /* For now we don't use buffer size field in the ADDBA request frame. The reci
pient | 1026 /* For now we don't use buffer size field in the ADDBA request frame. The reci
pient |
989 * will choose how many packets it can receive under block ack. | 1027 * will choose how many packets it can receive under block ack. |
990 */ | 1028 */ |
991 reqHdr.SetBufferSize (0); | 1029 reqHdr.SetBufferSize (0); |
992 reqHdr.SetTimeout (timeout); | 1030 reqHdr.SetTimeout (timeout); |
993 reqHdr.SetStartingSequence (startSeq); | 1031 reqHdr.SetStartingSequence (startSeq); |
994 | 1032 |
995 m_baManager->CreateAgreement (&reqHdr, dest); | 1033 m_baManager->CreateAgreement (&reqHdr, dest); |
996 ·· | 1034 ·· |
997 packet->AddHeader (reqHdr); | 1035 packet->AddHeader (reqHdr); |
| 1036 packet->AddHeader (actionHdr); |
998 ·· | 1037 ·· |
999 m_currentPacket = packet; | 1038 m_currentPacket = packet; |
1000 m_currentHdr = hdr; | 1039 m_currentHdr = hdr; |
1001 | 1040 |
1002 uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr); | 1041 uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr); |
1003 m_currentHdr.SetSequenceNumber (sequence); | 1042 m_currentHdr.SetSequenceNumber (sequence); |
1004 m_currentHdr.SetFragmentNumber (0); | 1043 m_currentHdr.SetFragmentNumber (0); |
1005 m_currentHdr.SetNoMoreFragments (); | 1044 m_currentHdr.SetNoMoreFragments (); |
1006 m_currentHdr.SetNoRetry (); | 1045 m_currentHdr.SetNoRetry (); |
1007 ·· | 1046 ·· |
1008 MacLowTransmissionParameters params; | 1047 MacLowTransmissionParameters params; |
1009 params.EnableAck (); | 1048 params.EnableAck (); |
1010 params.DisableRts (); | 1049 params.DisableRts (); |
1011 params.DisableNextData (); | 1050 params.DisableNextData (); |
1012 params.DisableOverrideDurationId (); | 1051 params.DisableOverrideDurationId (); |
1013 ·· | 1052 ·· |
1014 m_low->StartTransmission (m_currentPacket, &m_currentHdr, params,· | 1053 m_low->StartTransmission (m_currentPacket, &m_currentHdr, params,· |
1015 m_transmissionListener); | 1054 m_transmissionListener); |
1016 } | 1055 } |
1017 | 1056 |
| 1057 void |
| 1058 EdcaTxopN::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator) |
| 1059 { |
| 1060 WifiMacHeader hdr; |
| 1061 hdr.SetAction (); |
| 1062 hdr.SetAddr1 (addr); |
| 1063 hdr.SetAddr2 (m_low->GetAddress ()); |
| 1064 hdr.SetAddr3 (m_low->GetAddress ()); |
| 1065 hdr.SetDsNotTo (); |
| 1066 hdr.SetDsNotFrom (); |
| 1067 |
| 1068 MgtDelBaHeader delbaHdr; |
| 1069 delbaHdr.SetTid (tid); |
| 1070 if (byOriginator) |
| 1071 { |
| 1072 delbaHdr.SetByOriginator (); |
| 1073 } |
| 1074 else |
| 1075 { |
| 1076 delbaHdr.SetByRecipient (); |
| 1077 } |
| 1078 |
| 1079 WifiActionHeader actionHdr; |
| 1080 WifiActionHeader::ActionValue action; |
| 1081 action.blockAck = WifiActionHeader::BLOCK_ACK_DELBA; |
| 1082 actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action); |
| 1083 ·· |
| 1084 Ptr<Packet> packet = Create<Packet> (); |
| 1085 packet->AddHeader (delbaHdr); |
| 1086 packet->AddHeader (actionHdr); |
| 1087 |
| 1088 PushFront (packet, hdr); |
| 1089 } |
| 1090 |
1018 } //namespace ns3 | 1091 } //namespace ns3 |
LEFT | RIGHT |