Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | |
2 /* | |
3 * Copyright (c) 2009 University of Washington | |
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 as published by | |
7 * the Free Software Foundation, either version 3 of the License, or | |
8 * (at your option) any later version. | |
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, see <http://www.gnu.org/licenses/>. | |
17 * | |
18 * Author: Leonard Tracy <lentracy@u.washington.edu> | |
19 * | |
20 * | |
21 */ | |
22 | |
23 | |
24 #include "uan-mac-rc.h" | |
25 #include "uan-header-rc.h" | |
26 #include "uan-tx-mode.h" | |
27 #include "uan-phy.h" | |
28 #include "uan-header-common.h" | |
29 #include "uan-phy-dual.h" | |
30 | |
31 #include "ns3/log.h" | |
32 #include "ns3/nstime.h" | |
33 #include "ns3/simulator.h" | |
34 #include "ns3/random-variable.h" | |
35 #include "ns3/assert.h" | |
36 #include "ns3/double.h" | |
37 #include "ns3/uinteger.h" | |
38 | |
39 #include <list> | |
40 #include <utility> | |
41 | |
42 | |
43 NS_LOG_COMPONENT_DEFINE ("UanMacRc"); | |
44 namespace ns3 | |
45 { | |
46 | |
47 uint32_t m_cntrlSends=0; | |
Andrey Mazo
2009/11/15 13:32:11
Why not to make it UanMacRc private static variabl
| |
48 | |
49 NS_OBJECT_ENSURE_REGISTERED (UanMacRc); | |
50 | |
51 | |
52 Reservation::Reservation () | |
53 : m_length (0), | |
54 m_frameNo (0), | |
55 m_retryNo (0), | |
56 m_transmitted (false) | |
57 { | |
58 | |
59 } | |
60 | |
61 Reservation::Reservation (std::list<std::pair <Ptr<Packet>, UanAddress > > &list , uint8_t frameNo, uint32_t maxPkts) | |
62 : m_frameNo (frameNo), | |
63 m_retryNo (0), | |
64 m_transmitted (false) | |
65 { | |
66 uint32_t numPkts = (maxPkts)?maxPkts:list.size (); | |
67 uint32_t length = 0; | |
68 UanHeaderRcData dh; | |
69 UanHeaderCommon ch; | |
70 | |
71 for (uint32_t i=0;i<numPkts;i++) | |
72 { | |
73 | |
74 length += list.front ().first->GetSize () + | |
75 ch.GetSerializedSize () + | |
76 dh.GetSerializedSize (); | |
77 m_pktList.push_back (list.front ()); | |
78 list.pop_front (); | |
79 } | |
80 m_length = length; | |
81 } | |
82 | |
83 Reservation::~Reservation() | |
84 { | |
85 std::list<std::pair <Ptr<Packet>, UanAddress > >::iterator it; | |
86 for (it=m_pktList.begin (); it != m_pktList.end (); it++) | |
87 { | |
88 it->first = Ptr<Packet> ((Packet *) 0); | |
89 } | |
90 m_pktList.clear (); | |
91 m_timestamp.clear (); | |
92 } | |
93 uint32_t | |
94 Reservation::GetNoFrames () const | |
95 { | |
96 return m_pktList.size(); | |
97 } | |
98 | |
99 uint32_t | |
100 Reservation::GetLength () const | |
101 { | |
102 return m_length; | |
103 } | |
104 | |
105 const std::list<std::pair <Ptr<Packet>, UanAddress > > & | |
106 Reservation::GetPktList (void) const | |
107 { | |
108 return m_pktList; | |
109 } | |
110 | |
111 uint8_t | |
112 Reservation::GetFrameNo () const | |
113 { | |
114 return m_frameNo; | |
115 } | |
116 | |
117 uint8_t | |
118 Reservation::GetRetryNo () const | |
119 { | |
120 return m_retryNo; | |
121 } | |
122 | |
123 Time | |
124 Reservation::GetTimestamp (uint8_t n) const | |
125 { | |
126 return m_timestamp[n]; | |
127 } | |
128 | |
129 bool | |
130 Reservation::IsTransmitted () const | |
131 { | |
132 return m_transmitted; | |
133 } | |
134 | |
135 void | |
136 Reservation::SetFrameNo (uint8_t fn) | |
137 { | |
138 m_frameNo = fn; | |
139 } | |
140 | |
141 void | |
142 Reservation::AddTimestamp (Time t) | |
143 { | |
144 m_timestamp.push_back(t); | |
145 } | |
146 | |
147 void | |
148 Reservation::IncrementRetry () | |
149 { | |
150 m_retryNo++; | |
151 } | |
152 | |
153 void | |
154 Reservation::SetTransmitted (bool t) | |
155 { | |
156 m_transmitted = true; | |
157 } | |
158 | |
159 | |
160 UanMacRc::UanMacRc () : | |
161 m_state (UNASSOCIATED), | |
162 m_rtsBlocked (false), | |
163 m_currentRate (10), | |
164 m_frameNo (0) | |
165 { | |
166 UanHeaderCommon ch; | |
167 UanHeaderRcCts ctsh; | |
168 UanHeaderRcCtsGlobal ctsg; | |
169 | |
170 m_ctsSizeN = ctsh.GetSerializedSize (); | |
171 m_ctsSizeG = ch.GetSerializedSize () + ctsg.GetSerializedSize (); | |
172 | |
173 | |
174 } | |
175 | |
176 UanMacRc::~UanMacRc () | |
177 { | |
178 } | |
179 | |
180 void | |
181 UanMacRc::DoDispose () | |
182 { | |
183 m_phy = 0; | |
184 std::list<std::pair <Ptr<Packet>, UanAddress > >::iterator it; | |
185 for(it=m_pktQueue.begin (); it != m_pktQueue.end (); it++) | |
186 { | |
187 it->first = Ptr<Packet> ((Packet *) 0); | |
188 } | |
189 m_pktQueue.clear (); | |
190 m_resList.clear (); | |
191 Object::DoDispose (); | |
192 } | |
193 TypeId | |
194 UanMacRc::GetTypeId (void) | |
195 { | |
196 TypeId tid = TypeId ("ns3::UanMacRc") | |
197 .SetParent<UanMac> () | |
198 .AddConstructor<UanMacRc> () | |
199 .AddAttribute ("RetryRate", | |
200 "Number of retry attempts per second (of RTS/GWPING)", | |
201 DoubleValue (1/5.0), | |
202 MakeDoubleAccessor (&UanMacRc::m_retryRate), | |
203 MakeDoubleChecker<double> ()) | |
204 .AddAttribute ("MaxFrames", | |
205 "Maximum number of frames to include in a single RTS", | |
206 UintegerValue (1), | |
207 MakeUintegerAccessor (&UanMacRc::m_maxFrames), | |
208 MakeUintegerChecker<uint32_t> ()) | |
209 .AddAttribute ("QueueLimit", | |
210 "Maximum packets to queue at MAC", | |
211 UintegerValue (10), | |
212 MakeUintegerAccessor (&UanMacRc::m_queueLimit), | |
213 MakeUintegerChecker<uint32_t> ()) | |
214 .AddAttribute ("SIFS", | |
215 "Spacing to give between frames (this should match gateway)" , | |
216 TimeValue (Seconds (0.2)), | |
217 MakeTimeAccessor (&UanMacRc::m_sifs), | |
218 MakeTimeChecker ()) | |
219 .AddAttribute ("NumberOfRates", | |
220 "Number of rate divisions supported by each PHY", | |
221 UintegerValue (0), | |
222 MakeUintegerAccessor (&UanMacRc::m_numRates), | |
223 MakeUintegerChecker<uint32_t> ()) | |
224 .AddAttribute ("MinRetryRate", | |
225 "Smallest allowed RTS retry rate", | |
226 DoubleValue(0.01), | |
227 MakeDoubleAccessor (&UanMacRc::m_minRetryRate), | |
228 MakeDoubleChecker<double> ()) | |
229 .AddAttribute ("RetryStep", | |
230 "Retry rate increment", | |
231 DoubleValue (0.01), | |
232 MakeDoubleAccessor (&UanMacRc::m_retryStep), | |
233 MakeDoubleChecker<double> ()) | |
234 .AddAttribute ("NumberOfRetryRates", | |
235 "Number of retry rates", | |
236 UintegerValue (100), | |
237 MakeUintegerAccessor (&UanMacRc::m_numRetryRates), | |
238 MakeUintegerChecker<uint16_t> ()) | |
239 .AddAttribute ("MaxPropDelay", | |
240 "Maximum possible propagation delay to gateway", | |
241 TimeValue (Seconds (2)), | |
242 MakeTimeAccessor (&UanMacRc::m_learnedProp), | |
243 MakeTimeChecker ()) | |
244 .AddTraceSource ("Enqueue", | |
245 "A (data) packet arrived at MAC for transmission", | |
246 MakeTraceSourceAccessor (&UanMacRc::m_enqueueLogger)) | |
247 .AddTraceSource ("Dequeue", | |
248 "A (data) packet was passed down to PHY from MAC", | |
249 MakeTraceSourceAccessor (&UanMacRc::m_dequeueLogger)) | |
250 .AddTraceSource ("RX", | |
251 "A packet was destined for and received at this MAC layer" , | |
252 MakeTraceSourceAccessor (&UanMacRc::m_rxLogger)) | |
253 | |
254 ; | |
255 return tid; | |
256 } | |
257 | |
258 | |
259 Address | |
260 UanMacRc::GetAddress (void) | |
261 { | |
262 return m_address; | |
263 } | |
264 void | |
265 UanMacRc::SetAddress (UanAddress addr) | |
266 { | |
267 m_address = addr; | |
268 } | |
269 bool | |
270 UanMacRc::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNum ber) | |
271 { | |
272 if (protocolNumber > 0) | |
273 NS_LOG_WARN ("Warning: UanMacRc does not support multiple protocols. protoc olNumber argument to Enqueue is being ignored"); | |
274 | |
275 | |
276 if (m_pktQueue.size () >= m_queueLimit) | |
277 return false; | |
278 | |
279 m_pktQueue.push_back (std::make_pair (packet, UanAddress::ConvertFrom (dest))) ; | |
280 | |
281 switch (m_state) | |
282 { | |
283 case UNASSOCIATED: | |
284 Associate (); | |
285 return true; | |
286 case IDLE: | |
287 if (!m_rtsEvent.IsRunning ()) | |
288 SendRts (); | |
289 return true; | |
290 case GWPSENT: | |
291 case RTSSENT: | |
292 case DATATX: | |
293 return true; | |
294 } | |
295 | |
296 return true; | |
297 } | |
298 void | |
299 UanMacRc::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb) | |
300 { | |
301 m_forwardUpCb = cb; | |
302 } | |
303 void | |
304 UanMacRc::AttachPhy (Ptr<UanPhy> phy) | |
305 { | |
306 m_phy = phy; | |
307 m_phy->SetReceiveOkCallback (MakeCallback (&UanMacRc::ReceiveOkFromPhy, this)) ; | |
308 } | |
309 | |
310 Address | |
311 UanMacRc::GetBroadcast (void) const | |
312 { | |
313 return UanAddress::GetBroadcast (); | |
314 } | |
315 | |
316 void | |
317 UanMacRc::ReceiveOkFromPhy (Ptr<Packet> pkt, double sinr, UanTxMode mode) | |
318 { | |
319 | |
320 UanHeaderCommon ch; | |
321 pkt->RemoveHeader (ch); | |
322 if (ch.GetDest () == m_address || ch.GetDest () == UanAddress::GetBroadcast () ) | |
323 m_rxLogger (pkt, mode); | |
324 | |
325 switch (ch.GetType ()) | |
326 { | |
327 case TYPE_DATA: | |
328 | |
329 if (ch.GetDest () == m_address) | |
330 { | |
331 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " UanMacRc Receiving DATA packet from PHY"); | |
332 UanHeaderRcData dh; | |
333 pkt->RemoveHeader (dh); | |
334 m_forwardUpCb (pkt, ch.GetSrc ()); | |
335 } | |
336 break; | |
337 case TYPE_RTS: | |
338 //Currently don't respond to RTS packets at non-gateway nodes | |
339 //(Code assumes signle network neighberhood) | |
340 break; | |
341 case TYPE_CTS: | |
342 { | |
343 uint32_t ctsBytes = ch.GetSerializedSize () + pkt->GetSize (); | |
344 m_assocAddr = ch.GetSrc(); | |
345 UanHeaderRcCtsGlobal ctsg; | |
346 pkt->RemoveHeader (ctsg); | |
347 m_currentRate = ctsg.GetRateNum (); | |
348 m_retryRate = m_minRetryRate + m_retryStep*ctsg.GetRetryRate (); | |
349 | |
350 UanHeaderRcRts rhtmp; | |
351 | |
352 Time winDelay = ctsg.GetWindowTime (); | |
353 | |
354 if (winDelay.GetSeconds () > 0) | |
355 { | |
356 m_rtsBlocked = false; | |
357 Simulator::Schedule (winDelay, &UanMacRc::BlockRtsing, this); | |
358 } | |
359 else | |
360 { | |
361 NS_FATAL_ERROR (Simulator::Now ().GetSeconds () << " Node " << m_addre ss << " Received window period < 0"); | |
362 } | |
363 | |
364 UanHeaderRcCts ctsh; | |
365 ctsh.SetAddress (UanAddress::GetBroadcast ()); | |
366 while (pkt->GetSize () > 0) | |
367 { | |
368 pkt->RemoveHeader (ctsh); | |
369 if (ctsh.GetAddress () == m_address) | |
370 { | |
371 if (m_state == GWPSENT) | |
372 { | |
373 m_assocAddr = ch.GetSrc (); | |
374 ScheduleData (ctsh, ctsg, ctsBytes); | |
375 } | |
376 else if (m_state == RTSSENT) | |
377 { | |
378 ScheduleData (ctsh, ctsg, ctsBytes); | |
379 } | |
380 else | |
381 { | |
382 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m _address << " received CTS while state != RTSSENT or GWPING"); | |
383 } | |
384 } | |
385 } | |
386 } | |
387 break; | |
388 case TYPE_GWPING: | |
389 //Do not respond to GWPINGS at non-gateway nodes | |
390 break; | |
391 case TYPE_ACK: | |
392 m_rtsBlocked = true; | |
393 if (ch.GetDest () != m_address) | |
394 return; | |
395 ProcessAck (pkt); | |
396 break; | |
397 default: | |
398 NS_FATAL_ERROR ("Unknown packet type " << ch.GetType () << " received at n ode " << GetAddress ()); | |
399 } | |
400 | |
401 } | |
402 | |
403 void | |
404 UanMacRc::ScheduleData (const UanHeaderRcCts &ctsh, const UanHeaderRcCtsGlobal & ctsg, uint32_t ctsBytes) | |
405 { | |
406 NS_ASSERT (m_state == RTSSENT || m_state == GWPSENT); | |
407 | |
408 | |
409 | |
410 std::list<Reservation>::iterator it = m_resList.begin (); | |
411 for (;it != m_resList.end ();it++) | |
412 { | |
413 if (it->GetFrameNo () == ctsh.GetFrameNo ()) | |
414 break; | |
415 } | |
416 if (it == m_resList.end ()) | |
417 { | |
418 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS packet with no corresponding reservation!"); | |
419 //NS_FATAL_ERROR ("In " << __func__ << " could not find reservation corres ponding to received CTS"); | |
420 return; | |
421 } | |
422 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " re ceived CTS packet. Scheduling data"); | |
423 it->SetTransmitted (); | |
424 | |
425 double currentBps = m_phy->GetMode (m_currentRate).GetDataRateBps (); | |
426 | |
427 m_learnedProp = Simulator::Now () - ctsg.GetTxTimeStamp () - Seconds (ctsBytes *8.0 / currentBps); | |
428 | |
429 | |
430 Time arrTime = ctsg.GetTxTimeStamp () + ctsh.GetDelayToTx (); | |
431 Time txTime = arrTime - m_learnedProp; | |
432 | |
433 Time startDelay = txTime - Simulator::Now (); | |
434 | |
435 Time frameDelay = Seconds (0); | |
436 | |
437 const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList (); | |
438 std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit; | |
439 pit = l.begin (); | |
440 | |
441 | |
442 | |
443 for (uint32_t i=0;i<it->GetNoFrames ();i++, pit++) | |
444 { | |
445 Ptr<Packet> pkt = (*pit).first->Copy (); | |
446 | |
447 UanHeaderRcData dh; | |
448 dh.SetFrameNo (i); | |
449 dh.SetPropDelay (m_learnedProp); | |
450 pkt->AddHeader (dh); | |
451 | |
452 UanHeaderCommon ch; | |
453 ch.SetType (TYPE_DATA); | |
454 ch.SetDest (m_assocAddr); | |
455 ch.SetSrc (m_address); | |
456 | |
457 pkt->AddHeader (ch); | |
458 Time eventTime = startDelay + frameDelay; | |
459 if (eventTime.GetSeconds () < 0) | |
460 { | |
461 if (eventTime.GetSeconds () > -0.001) | |
462 { | |
463 eventTime = Seconds (0); | |
464 } | |
465 else | |
466 { | |
467 NS_FATAL_ERROR ("Scheduling error resulted in very negative data t ransmission time! eventTime = " << eventTime.GetSeconds ()); | |
468 } | |
469 } | |
470 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " scheduling with delay " << eventTime.GetSeconds () << " propDelay " << m_learn edProp.GetSeconds () << " start delay " << startDelay.GetSeconds () << " arrival time " << arrTime.GetSeconds ()); | |
471 Simulator::Schedule (eventTime, &UanMacRc::SendPacket, this, pkt, m_curren tRate); | |
472 frameDelay = frameDelay + m_sifs + Seconds (pkt->GetSize ()/currentBps); | |
473 } | |
474 | |
475 m_state = IDLE; | |
476 if (!m_pktQueue.empty ()) | |
477 { | |
478 | |
479 if (m_rtsEvent.IsRunning ()) | |
480 { | |
481 m_rtsEvent.Cancel (); | |
482 } | |
483 ExponentialVariable ev (1/m_retryRate); | |
484 double timeout = ev.GetValue (); | |
485 m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::SendRts, t his); | |
486 } | |
487 | |
488 } | |
489 | |
490 void | |
491 UanMacRc::SendPacket (Ptr<Packet> pkt, uint32_t rate) | |
492 { | |
493 UanHeaderCommon ch; | |
494 pkt->PeekHeader (ch); | |
495 std::string type; | |
496 switch (ch.GetType ()) | |
497 { | |
498 case TYPE_DATA: | |
499 type = "DATA"; | |
500 break; | |
501 case TYPE_RTS: | |
502 type= "RTS"; | |
503 break; | |
504 case TYPE_CTS: | |
505 type="CTS"; | |
506 break; | |
507 case TYPE_ACK: | |
508 type="ACK"; | |
509 break; | |
510 case TYPE_GWPING: | |
511 type="GWPING"; | |
512 break; | |
513 default: | |
514 type="UNKNOWN"; | |
515 break; | |
516 } | |
517 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " tr ansmitting " << pkt->GetSize () << " byte packet of type " << type << " with rat e " << rate << "(" << m_phy->GetMode (rate).GetDataRateBps () << ") to " << ch.G etDest ()); | |
518 m_dequeueLogger (pkt, rate); | |
519 m_phy->SendPacket (pkt, rate); | |
520 } | |
521 | |
522 void | |
523 UanMacRc::ProcessAck (Ptr<Packet> ack) | |
524 { | |
525 UanHeaderRcAck ah; | |
526 ack->RemoveHeader (ah); | |
527 | |
528 std::list<Reservation>::iterator it = m_resList.begin (); | |
529 for (;it != m_resList.end ();it++) | |
530 { | |
531 if (it->GetFrameNo () == ah.GetFrameNo ()) | |
532 break; | |
533 } | |
534 if (it == m_resList.end ()) | |
535 { | |
536 NS_LOG_DEBUG ("In " << __func__ << " could not find reservation correspond ing to received ACK"); | |
537 return; | |
538 } | |
539 if (!it->IsTransmitted ()) | |
540 return; | |
541 if (ah.GetNoNacks () > 0) | |
542 { | |
543 const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList (); | |
544 std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit; | |
545 pit = l.begin (); | |
546 | |
547 const std::set<uint8_t> &nacks = ah.GetNackedFrames (); | |
548 std::set<uint8_t>::iterator nit = nacks.begin (); | |
549 uint8_t pnum=0; | |
550 for (;nit != nacks.end ();nit++) | |
551 { | |
552 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " Received NACK for " << (uint32_t) *nit); | |
553 while (pnum < *nit) | |
554 { | |
555 pit++; | |
556 pnum++; | |
557 } | |
558 UanHeaderRcData dh; | |
559 UanHeaderCommon ch; | |
560 m_pktQueue.push_front (*pit); | |
561 } | |
562 } | |
563 else | |
564 { | |
565 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received ACK for all frames"); | |
566 } | |
567 m_resList.erase (it); | |
568 } | |
569 | |
570 UanHeaderRcRts | |
571 UanMacRc::CreateRtsHeader (const Reservation &res) | |
572 { | |
573 UanHeaderRcRts rh = UanHeaderRcRts (); | |
574 | |
575 rh.SetLength (res.GetLength ()); | |
576 rh.SetNoFrames (res.GetNoFrames ()); | |
577 rh.SetTimeStamp (res.GetTimestamp (res.GetRetryNo ())); | |
578 rh.SetFrameNo (res.GetFrameNo ()); | |
579 rh.SetRetryNo (res.GetRetryNo ()); | |
580 return rh; | |
581 } | |
582 | |
583 void | |
584 UanMacRc::Associate (void) | |
585 { | |
586 m_cntrlSends++; | |
587 | |
588 Reservation res (m_pktQueue, m_frameNo, m_maxFrames); | |
589 res.AddTimestamp (Simulator::Now ()); | |
590 m_frameNo++; | |
591 m_resList.push_back (res); | |
592 Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> (); | |
593 bool phy1ok = IsPhy1Ok (); | |
594 if (phy1ok && !phyDual->IsPhy2Tx () & !m_rtsBlocked) | |
595 { | |
596 Ptr<Packet> pkt = Create<Packet> (0); | |
597 pkt->AddHeader (CreateRtsHeader (res)); | |
598 pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), ( uint8_t) TYPE_GWPING)); | |
599 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending first GWPING " << *pkt); | |
600 SendPacket (pkt,m_currentRate + m_numRates); | |
601 } | |
602 m_state = GWPSENT; | |
603 NS_ASSERT (!m_rtsEvent.IsRunning ()); | |
604 ExponentialVariable ev (1.0/m_retryRate); | |
605 double timeout = ev.GetValue (); | |
606 m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::AssociateTimeo ut, this); | |
607 } | |
608 | |
609 void | |
610 UanMacRc::AssociateTimeout () | |
611 { | |
612 m_cntrlSends++; | |
613 if (m_state != GWPSENT) | |
614 return; | |
615 Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> (); | |
616 bool phy1ok = IsPhy1Ok (); | |
617 if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked) | |
618 { | |
619 Ptr<Packet> pkt = Create<Packet> (); | |
620 | |
621 | |
622 Reservation res = m_resList.back (); | |
623 m_resList.pop_back (); | |
624 res.AddTimestamp (Simulator::Now ()); | |
625 res.IncrementRetry (); | |
626 | |
627 pkt->AddHeader (CreateRtsHeader (res)); | |
628 pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), ( uint8_t) TYPE_GWPING)); | |
629 | |
630 SendPacket (pkt,m_currentRate + m_numRates); | |
631 m_resList.push_back (res); | |
632 } | |
633 NS_ASSERT (!m_rtsEvent.IsRunning ()); | |
634 ExponentialVariable ev (1.0/m_retryRate); | |
635 double timeout = ev.GetValue (); | |
636 m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::AssociateTimeo ut, this); | |
637 | |
638 } | |
639 | |
640 | |
641 void | |
642 UanMacRc::SendRts (void) | |
643 { | |
644 m_cntrlSends++; | |
645 if (m_state == RTSSENT) | |
646 return; | |
647 | |
648 NS_ASSERT (!m_pktQueue.empty ()); | |
649 | |
650 Reservation res (m_pktQueue, m_frameNo, m_maxFrames); | |
651 res.AddTimestamp (Simulator::Now ()); | |
652 m_frameNo++; | |
653 m_resList.push_back (res); | |
654 Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> (); | |
655 bool phy1ok = IsPhy1Ok (); | |
656 if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked ) | |
657 { | |
658 Ptr<Packet> pkt = Create<Packet> (0); | |
659 pkt->AddHeader (CreateRtsHeader (res)); | |
660 pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), ( uint8_t) TYPE_RTS)); | |
661 SendPacket (pkt,m_currentRate + m_numRates); | |
662 } | |
663 m_state = RTSSENT; | |
664 NS_ASSERT (!m_rtsEvent.IsRunning ()); | |
665 ExponentialVariable ev (1.0/m_retryRate); | |
666 double timeout = ev.GetValue (); | |
667 m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::RtsTimeout, th is); | |
668 | |
669 } | |
670 | |
671 //This is a bit of a cheat. Basically under the assumption here | |
faker.moatamri
2009/10/21 10:24:09
Will it remain like that? is there a plan to chang
| |
672 //that the PHY layer will have knowledge of packet type shortly after arrival. | |
673 //We do not want to transmit control packets while receiving control information | |
674 //or packets addressed to us. | |
675 bool | |
676 UanMacRc::IsPhy1Ok () | |
677 { | |
678 Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> (); | |
679 | |
680 bool phy1ok = true; | |
681 if (phyDual->IsPhy1Rx ()) | |
682 { | |
683 Ptr<Packet> pkt = phyDual->GetPhy1PacketRx (); | |
684 UanHeaderCommon ch; | |
685 pkt->PeekHeader (ch); | |
686 if (ch.GetType () == TYPE_CTS || ch.GetType () == TYPE_ACK) | |
687 phy1ok = false; | |
688 else if (ch.GetDest () == m_address) | |
689 phy1ok = false; | |
690 } | |
691 return phy1ok; | |
692 } | |
693 void | |
694 UanMacRc::RtsTimeout (void) | |
695 { | |
696 m_cntrlSends++; | |
697 | |
698 if (m_state != RTSSENT) | |
699 return; | |
700 Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual>(); | |
701 | |
702 bool phy1ok = IsPhy1Ok (); | |
703 if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked) | |
704 { | |
705 | |
706 if (m_resList.empty ()) | |
707 { | |
708 NS_FATAL_ERROR (Simulator::Now ().GetSeconds () << " Node " << m_addre ss << " tried to retry RTS with empty reservation list"); | |
709 } | |
710 Ptr<Packet> pkt = Create<Packet> (0); | |
711 | |
712 Reservation res = m_resList.back (); | |
713 NS_ASSERT (!res.IsTransmitted ()); | |
714 m_resList.pop_back (); | |
715 res.AddTimestamp (Simulator::Now ()); | |
716 res.IncrementRetry (); | |
717 m_resList.push_back (res); | |
718 pkt->AddHeader (CreateRtsHeader (res)); | |
719 pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), ( uint8_t) TYPE_RTS)); | |
720 SendPacket (pkt,m_currentRate + m_numRates); | |
721 | |
722 } | |
723 m_state = RTSSENT; | |
724 NS_ASSERT (!m_rtsEvent.IsRunning ()); | |
725 ExponentialVariable ev (1.0/m_retryRate); | |
726 double timeout = ev.GetValue (); | |
727 m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::RtsTimeout, th is); | |
728 } | |
729 | |
730 | |
731 } //namespace ns3 | |
OLD | NEW |