|
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2004,2005,2006 INRIA |
|
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> |
|
19 */ |
|
20 |
|
21 #include "arf-wifi-manager.h" |
|
22 #include "ns3/assert.h" |
|
23 #include "ns3/log.h" |
|
24 #include "ns3/uinteger.h" |
|
25 |
|
26 NS_LOG_COMPONENT_DEFINE ("ns3::ArfWifiManager"); |
|
27 |
|
28 |
|
29 namespace ns3 { |
|
30 |
|
31 struct ArfWifiRemoteStation : public WifiRemoteStation |
|
32 { |
|
33 uint32_t m_timer; |
|
34 uint32_t m_success; |
|
35 uint32_t m_failed; |
|
36 bool m_recovery; |
|
37 uint32_t m_retry; |
|
38 |
|
39 uint32_t m_timerTimeout; |
|
40 uint32_t m_successThreshold; |
|
41 |
|
42 uint32_t m_rate; |
|
43 }; |
|
44 |
|
45 NS_OBJECT_ENSURE_REGISTERED (ArfWifiManager); |
|
46 |
|
47 TypeId |
|
48 ArfWifiManager::GetTypeId (void) |
|
49 { |
|
50 static TypeId tid = TypeId ("ns3::ArfWifiManager") |
|
51 .SetParent<WifiRemoteStationManager> () |
|
52 .AddConstructor<ArfWifiManager> () |
|
53 .AddAttribute ("TimerThreshold", "The 'timer' threshold in the ARF algorithm.", |
|
54 UintegerValue (15), |
|
55 MakeUintegerAccessor (&ArfWifiManager::m_timerThreshold), |
|
56 MakeUintegerChecker<uint32_t> ()) |
|
57 .AddAttribute ("SuccessThreshold", |
|
58 "The minimum number of sucessfull transmissions to try a new rate.", |
|
59 UintegerValue (10), |
|
60 MakeUintegerAccessor (&ArfWifiManager::m_successThreshold), |
|
61 MakeUintegerChecker<uint32_t> ()) |
|
62 ; |
|
63 return tid; |
|
64 } |
|
65 |
|
66 ArfWifiManager::ArfWifiManager () |
|
67 {} |
|
68 ArfWifiManager::~ArfWifiManager () |
|
69 {} |
|
70 WifiRemoteStation * |
|
71 ArfWifiManager::DoCreateStation (void) const |
|
72 { |
|
73 ArfWifiRemoteStation *station = new ArfWifiRemoteStation (); |
|
74 |
|
75 station->m_successThreshold = m_successThreshold; |
|
76 station->m_timerTimeout = m_timerThreshold; |
|
77 station->m_rate = 0; |
|
78 station->m_success = 0; |
|
79 station->m_failed = 0; |
|
80 station->m_recovery = false; |
|
81 station->m_retry = 0; |
|
82 station->m_timer = 0; |
|
83 |
|
84 return station; |
|
85 } |
|
86 |
|
87 void |
|
88 ArfWifiManager::DoReportRtsFailed (WifiRemoteStation *station) |
|
89 {} |
|
90 /** |
|
91 * It is important to realize that "recovery" mode starts after failure of |
|
92 * the first transmission after a rate increase and ends at the first successful |
|
93 * transmission. Specifically, recovery mode transcends retransmissions boundaries. |
|
94 * Fundamentally, ARF handles each data transmission independently, whether it |
|
95 * is the initial transmission of a packet or the retransmission of a packet. |
|
96 * The fundamental reason for this is that there is a backoff between each data |
|
97 * transmission, be it an initial transmission or a retransmission. |
|
98 */ |
|
99 void |
|
100 ArfWifiManager::DoReportDataFailed (WifiRemoteStation *st) |
|
101 { |
|
102 ArfWifiRemoteStation *station = (ArfWifiRemoteStation *)st; |
|
103 station->m_timer++; |
|
104 station->m_failed++; |
|
105 station->m_retry++; |
|
106 station->m_success = 0; |
|
107 |
|
108 if (station->m_recovery) |
|
109 { |
|
110 NS_ASSERT (station->m_retry >= 1); |
|
111 if (station->m_retry == 1) |
|
112 { |
|
113 // need recovery fallback |
|
114 if (station->m_rate != 0) |
|
115 { |
|
116 station->m_rate--; |
|
117 } |
|
118 } |
|
119 station->m_timer = 0; |
|
120 } |
|
121 else |
|
122 { |
|
123 NS_ASSERT (station->m_retry >= 1); |
|
124 if (((station->m_retry - 1) % 2) == 1) |
|
125 { |
|
126 // need normal fallback |
|
127 if (station->m_rate != 0) |
|
128 { |
|
129 station->m_rate--; |
|
130 } |
|
131 } |
|
132 if (station->m_retry >= 2) |
|
133 { |
|
134 station->m_timer = 0; |
|
135 } |
|
136 } |
|
137 } |
|
138 void |
|
139 ArfWifiManager::DoReportRxOk (WifiRemoteStation *station, |
|
140 double rxSnr, WifiMode txMode) |
|
141 {} |
|
142 void ArfWifiManager::DoReportRtsOk (WifiRemoteStation *station, |
|
143 double ctsSnr, WifiMode ctsMode, double rtsSnr) |
|
144 { |
|
145 NS_LOG_DEBUG ("station="<<station<<" rts ok"); |
|
146 } |
|
147 void ArfWifiManager::DoReportDataOk (WifiRemoteStation *st, |
|
148 double ackSnr, WifiMode ackMode, double dataSnr) |
|
149 { |
|
150 ArfWifiRemoteStation *station = (ArfWifiRemoteStation *) st; |
|
151 station->m_timer++; |
|
152 station->m_success++; |
|
153 station->m_failed = 0; |
|
154 station->m_recovery = false; |
|
155 station->m_retry = 0; |
|
156 NS_LOG_DEBUG ("station=" << station << " data ok success=" << station->m_success << ", timer=" << station->m_timer); |
|
157 if ((station->m_success == m_successThreshold || |
|
158 station->m_timer == m_timerThreshold) && |
|
159 (station->m_rate < (station->m_state->m_operationalRateSet.size () - 1))) |
|
160 { |
|
161 NS_LOG_DEBUG ("station="<<station<<" inc rate"); |
|
162 station->m_rate++; |
|
163 station->m_timer = 0; |
|
164 station->m_success = 0; |
|
165 station->m_recovery = true; |
|
166 } |
|
167 } |
|
168 void |
|
169 ArfWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station) |
|
170 {} |
|
171 void |
|
172 ArfWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station) |
|
173 {} |
|
174 |
|
175 WifiMode |
|
176 ArfWifiManager::DoGetDataMode (WifiRemoteStation *st, uint32_t size) |
|
177 { |
|
178 ArfWifiRemoteStation *station = (ArfWifiRemoteStation *) st; |
|
179 return GetSupported (station, station->m_rate); |
|
180 } |
|
181 WifiMode |
|
182 ArfWifiManager::DoGetRtsMode (WifiRemoteStation *st) |
|
183 { |
|
184 // XXX: we could/should implement the Arf algorithm for |
|
185 // RTS only by picking a single rate within the BasicRateSet. |
|
186 ArfWifiRemoteStation *station = (ArfWifiRemoteStation *) st; |
|
187 return GetSupported (station, 0); |
|
188 } |
|
189 |
|
190 bool |
|
191 ArfWifiManager::IsLowLatency (void) const |
|
192 { |
|
193 return true; |
|
194 } |
|
195 |
|
196 } // namespace ns3 |