53 HwmpRtable::DoDispose () |
54 HwmpRtable::DoDispose () |
54 { |
55 { |
55 m_routes.clear (); |
56 m_routes.clear (); |
56 } |
57 } |
57 void |
58 void |
58 HwmpRtable::AddReactivePath ( |
59 HwmpRtable::AddReactivePath (Mac48Address destination, Mac48Address retransmitter, uint32_t interface, |
59 Mac48Address destination, |
60 uint32_t metric, Time lifetime, uint32_t seqnum) |
60 Mac48Address retransmitter, |
|
61 uint32_t interface, |
|
62 uint32_t metric, |
|
63 Time lifetime, |
|
64 uint32_t seqnum |
|
65 ) |
|
66 { |
61 { |
67 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
62 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
68 if (i == m_routes.end ()) |
63 if (i == m_routes.end ()) |
69 { |
64 { |
70 ReactiveRoute newroute; |
65 ReactiveRoute newroute; |
71 m_routes[destination] = newroute; |
66 m_routes[destination] = newroute; |
72 } |
67 } |
73 i = m_routes.find (destination); |
68 i = m_routes.find (destination); |
74 NS_ASSERT (i != m_routes.end()); |
69 NS_ASSERT (i != m_routes.end ()); |
75 i->second.retransmitter = retransmitter; |
70 i->second.retransmitter = retransmitter; |
76 i->second.interface = interface; |
71 i->second.interface = interface; |
77 i->second.metric = metric; |
72 i->second.metric = metric; |
78 i->second.whenExpire = Simulator::Now() + lifetime; |
73 i->second.whenExpire = Simulator::Now () + lifetime; |
79 i->second.seqnum = seqnum; |
74 i->second.seqnum = seqnum; |
80 } |
75 } |
81 void |
76 void |
82 HwmpRtable::AddProactivePath ( |
77 HwmpRtable::AddProactivePath (uint32_t metric, Mac48Address root, Mac48Address retransmitter, |
83 uint32_t metric, |
78 uint32_t interface, Time lifetime, uint32_t seqnum) |
84 Mac48Address root, |
|
85 Mac48Address retransmitter, |
|
86 uint32_t interface, |
|
87 Time lifetime, |
|
88 uint32_t seqnum |
|
89 ) |
|
90 { |
79 { |
91 m_root.root = root; |
80 m_root.root = root; |
92 m_root.retransmitter = retransmitter; |
81 m_root.retransmitter = retransmitter; |
93 m_root.metric = metric; |
82 m_root.metric = metric; |
94 m_root.whenExpire = Simulator::Now() + lifetime; |
83 m_root.whenExpire = Simulator::Now () + lifetime; |
95 m_root.seqnum = seqnum; |
84 m_root.seqnum = seqnum; |
96 m_root.interface = interface; |
85 m_root.interface = interface; |
97 } |
86 } |
98 void |
87 void |
99 HwmpRtable::AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress) |
88 HwmpRtable::AddPrecursor (Mac48Address destination, uint32_t precursorInterface, |
|
89 Mac48Address precursorAddress) |
100 { |
90 { |
101 std::pair<uint32_t, Mac48Address> precursor; |
91 std::pair<uint32_t, Mac48Address> precursor; |
102 precursor.first = precursorInterface; |
92 precursor.first = precursorInterface; |
103 precursor.second = precursorAddress; |
93 precursor.second = precursorAddress; |
104 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
94 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
105 if (i != m_routes.end ()) |
95 if (i != m_routes.end ()) |
106 { |
96 { |
107 bool should_add = true; |
97 bool should_add = true; |
108 for (unsigned int j = 0 ; j < i->second.precursors.size (); j ++) |
98 for (unsigned int j = 0; j < i->second.precursors.size (); j++) |
109 //NB: Only one active route may exist, so do not check |
99 //NB: Only one active route may exist, so do not check |
110 //interface ID, just address |
100 //interface ID, just address |
111 if (i->second.precursors[j].second == precursorAddress) |
101 if (i->second.precursors[j].second == precursorAddress) |
112 { |
102 { |
113 should_add = false; |
103 should_add = false; |
114 break; |
104 break; |
115 } |
105 } |
116 if (should_add) |
106 if (should_add) |
117 i->second.precursors.push_back (precursor); |
107 { |
118 } |
108 i->second.precursors.push_back (precursor); |
119 if(m_root.root == destination) |
109 } |
120 for (unsigned int j = 0 ; j < m_root.precursors.size (); j ++) |
110 } |
121 if (m_root.precursors[j].second == precursorAddress) |
111 if (m_root.root == destination) |
122 return; |
112 { |
123 m_root.precursors.push_back(precursor); |
113 for (unsigned int j = 0; j < m_root.precursors.size (); j++) |
|
114 { |
|
115 if (m_root.precursors[j].second == precursorAddress) |
|
116 { |
|
117 return; |
|
118 } |
|
119 } |
|
120 } |
|
121 m_root.precursors.push_back (precursor); |
124 } |
122 } |
125 void |
123 void |
126 HwmpRtable::DeleteProactivePath () |
124 HwmpRtable::DeleteProactivePath () |
127 { |
125 { |
128 m_root.precursors.clear (); |
126 m_root.precursors.clear (); |
133 m_root.whenExpire = Simulator::Now (); |
131 m_root.whenExpire = Simulator::Now (); |
134 } |
132 } |
135 void |
133 void |
136 HwmpRtable::DeleteProactivePath (Mac48Address root) |
134 HwmpRtable::DeleteProactivePath (Mac48Address root) |
137 { |
135 { |
138 if(m_root.root == root) |
136 if (m_root.root == root) |
139 DeleteProactivePath (); |
137 DeleteProactivePath (); |
140 } |
138 } |
141 void |
139 void |
142 HwmpRtable::DeleteReactivePath (Mac48Address destination) |
140 HwmpRtable::DeleteReactivePath (Mac48Address destination) |
143 { |
141 { |
144 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
142 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
145 if (i != m_routes.end ()) |
143 if (i != m_routes.end ()) |
146 m_routes.erase (i); |
144 { |
|
145 m_routes.erase (i); |
|
146 } |
147 } |
147 } |
148 HwmpRtable::LookupResult |
148 HwmpRtable::LookupResult |
149 HwmpRtable::LookupReactive (Mac48Address destination) |
149 HwmpRtable::LookupReactive (Mac48Address destination) |
150 { |
150 { |
151 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
151 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
152 if (i == m_routes.end ()) |
152 if (i == m_routes.end ()) |
153 return LookupResult (); |
153 { |
|
154 return LookupResult (); |
|
155 } |
154 if ((i->second.whenExpire < Simulator::Now ()) && (i->second.whenExpire != Seconds (0))) |
156 if ((i->second.whenExpire < Simulator::Now ()) && (i->second.whenExpire != Seconds (0))) |
155 { |
157 { |
156 NS_LOG_DEBUG ("Reactive route has expired, sorry."); |
158 NS_LOG_DEBUG ("Reactive route has expired, sorry."); |
157 return LookupResult(); |
159 return LookupResult (); |
158 } |
160 } |
159 return LookupReactiveExpired (destination); |
161 return LookupReactiveExpired (destination); |
160 } |
162 } |
161 HwmpRtable::LookupResult |
163 HwmpRtable::LookupResult |
162 HwmpRtable::LookupReactiveExpired (Mac48Address destination) |
164 HwmpRtable::LookupReactiveExpired (Mac48Address destination) |
163 { |
165 { |
164 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
166 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination); |
165 if (i == m_routes.end ()) |
167 if (i == m_routes.end ()) |
166 return LookupResult (); |
168 { |
167 return LookupResult ( |
169 return LookupResult (); |
168 i->second.retransmitter, |
170 } |
169 i->second.interface, |
171 return LookupResult (i->second.retransmitter, i->second.interface, i->second.metric, i->second.seqnum, |
170 i->second.metric, i->second.seqnum, |
172 i->second.whenExpire - Simulator::Now ()); |
171 i->second.whenExpire - Simulator::Now () |
|
172 ); |
|
173 } |
173 } |
174 HwmpRtable::LookupResult |
174 HwmpRtable::LookupResult |
175 HwmpRtable::LookupProactive () |
175 HwmpRtable::LookupProactive () |
176 { |
176 { |
177 if (m_root.whenExpire < Simulator::Now ()) |
177 if (m_root.whenExpire < Simulator::Now ()) |
182 return LookupProactiveExpired (); |
182 return LookupProactiveExpired (); |
183 } |
183 } |
184 HwmpRtable::LookupResult |
184 HwmpRtable::LookupResult |
185 HwmpRtable::LookupProactiveExpired () |
185 HwmpRtable::LookupProactiveExpired () |
186 { |
186 { |
187 return LookupResult(m_root.retransmitter, m_root.interface, m_root.metric, m_root.seqnum, m_root.whenExpire - Simulator::Now ()); |
187 return LookupResult (m_root.retransmitter, m_root.interface, m_root.metric, m_root.seqnum, |
|
188 m_root.whenExpire - Simulator::Now ()); |
188 } |
189 } |
189 std::vector<IePerr::FailedDestination> |
190 std::vector<IePerr::FailedDestination> |
190 HwmpRtable::GetUnreachableDestinations (Mac48Address peerAddress) |
191 HwmpRtable::GetUnreachableDestinations (Mac48Address peerAddress) |
191 { |
192 { |
192 IePerr::FailedDestination dst; |
193 IePerr::FailedDestination dst; |
193 std::vector<IePerr::FailedDestination> retval; |
194 std::vector<IePerr::FailedDestination> retval; |
194 for (std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.begin (); i != m_routes.end(); i++) |
195 for (std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.begin (); i != m_routes.end (); i++) |
195 if (i->second.retransmitter == peerAddress) |
196 if (i->second.retransmitter == peerAddress) |
196 { |
197 { |
197 dst.destination = i->first; |
198 dst.destination = i->first; |
198 i->second.seqnum ++; |
199 i->second.seqnum++; |
199 dst.seqnum = i->second.seqnum; |
200 dst.seqnum = i->second.seqnum; |
200 retval.push_back (dst); |
201 retval.push_back (dst); |
201 } |
202 } |
202 //Lookup a path to root |
203 //Lookup a path to root |
203 if (m_root.retransmitter == peerAddress) |
204 if (m_root.retransmitter == peerAddress) |
213 { |
214 { |
214 //We suppose that no duplicates here can be |
215 //We suppose that no duplicates here can be |
215 PrecursorList retval; |
216 PrecursorList retval; |
216 std::map<Mac48Address, ReactiveRoute>::iterator route = m_routes.find (destination); |
217 std::map<Mac48Address, ReactiveRoute>::iterator route = m_routes.find (destination); |
217 if (route != m_routes.end ()) |
218 if (route != m_routes.end ()) |
218 for (unsigned int i = 0; i < route->second.precursors.size (); i ++) |
219 { |
219 retval.push_back(route->second.precursors[i]); |
220 for (unsigned int i = 0; i < route->second.precursors.size (); i++) |
|
221 { |
|
222 retval.push_back (route->second.precursors[i]); |
|
223 } |
|
224 } |
220 if (m_root.root == destination) |
225 if (m_root.root == destination) |
221 for (unsigned int i = 0; i < m_root.precursors.size (); i ++) |
226 { |
222 { |
227 for (unsigned int i = 0; i < m_root.precursors.size (); i++) |
223 bool should_add = true; |
228 { |
224 for(unsigned int j = 0; j < retval.size(); j ++) |
229 bool should_add = true; |
225 if(retval[j].second == m_root.precursors[i].second) |
230 for (unsigned int j = 0; j < retval.size (); j++) |
226 { |
231 if (retval[j].second == m_root.precursors[i].second) |
227 should_add = false; |
232 { |
228 break; |
233 should_add = false; |
229 } |
234 break; |
230 if(should_add) |
235 } |
231 retval.push_back(m_root.precursors[i]); |
236 if (should_add) |
|
237 retval.push_back (m_root.precursors[i]); |
|
238 } |
232 } |
239 } |
233 return retval; |
240 return retval; |
234 } |
241 } |
235 bool HwmpRtable::LookupResult::operator==(const HwmpRtable::LookupResult & o) const |
242 bool |
236 { |
243 HwmpRtable::LookupResult::operator== (const HwmpRtable::LookupResult & o) const |
237 return (retransmitter == o.retransmitter |
244 { |
238 && ifIndex == o.ifIndex |
245 return (retransmitter == o.retransmitter && ifIndex == o.ifIndex && metric == o.metric && seqnum |
239 && metric == o.metric |
246 == o.seqnum); |
240 && seqnum == o.seqnum |
247 } |
241 ); |
248 bool |
242 } |
249 HwmpRtable::LookupResult::IsValid () const |
243 bool HwmpRtable::LookupResult::IsValid() const |
250 { |
244 { |
251 return !(retransmitter == Mac48Address::GetBroadcast () && ifIndex == INTERFACE_ANY && metric == MAX_METRIC |
245 return !( retransmitter == Mac48Address::GetBroadcast () |
252 && seqnum == 0); |
246 && ifIndex == INTERFACE_ANY |
|
247 && metric == MAX_METRIC |
|
248 && seqnum == 0 |
|
249 ); |
|
250 } |
253 } |
251 #ifdef RUN_SELF_TESTS |
254 #ifdef RUN_SELF_TESTS |
252 /// Unit test for HwmpRtable |
255 /// Unit test for HwmpRtable |
253 class HwmpRtableTest : public Test |
256 class HwmpRtableTest : public Test |
254 { |
257 { |
255 public: |
258 public: |
256 HwmpRtableTest (); |
259 HwmpRtableTest (); |
257 virtual bool RunTests(); |
260 virtual bool |
258 |
261 RunTests (); |
|
262 |
259 private: |
263 private: |
260 /// Test Add apth and lookup path; |
264 /// Test Add apth and lookup path; |
261 void TestLookup (); |
265 void |
|
266 TestLookup (); |
262 /** |
267 /** |
263 * \name Test add path and try to lookup after entry has expired |
268 * \name Test add path and try to lookup after entry has expired |
264 * \{ |
269 * \{ |
265 */ |
270 */ |
266 void TestAddPath (); |
271 void |
267 void TestExpire (); |
272 TestAddPath (); |
|
273 void |
|
274 TestExpire (); |
268 ///\} |
275 ///\} |
269 /** |
276 /** |
270 * \name Test add precursors and find precursor list in rtable |
277 * \name Test add precursors and find precursor list in rtable |
271 * \{ |
278 * \{ |
272 */ |
279 */ |
273 void TestPrecursorAdd (); |
280 void |
274 void TestPrecursorFind (); |
281 TestPrecursorAdd (); |
|
282 void |
|
283 TestPrecursorFind (); |
275 ///\} |
284 ///\} |
276 private: |
285 private: |
277 bool result; |
286 bool result; |
278 |
287 |
279 Mac48Address dst; |
288 Mac48Address dst; |
280 Mac48Address hop; |
289 Mac48Address hop; |
281 uint32_t iface; |
290 uint32_t iface; |
282 uint32_t metric; |
291 uint32_t metric; |
283 uint32_t seqnum; |
292 uint32_t seqnum; |
286 std::vector<Mac48Address> precursors; |
295 std::vector<Mac48Address> precursors; |
287 }; |
296 }; |
288 /// Test instance |
297 /// Test instance |
289 static HwmpRtableTest g_HwmpRtableTest; |
298 static HwmpRtableTest g_HwmpRtableTest; |
290 |
299 |
291 HwmpRtableTest::HwmpRtableTest () : Test ("Mesh/802.11s/HwmpRtable"), |
300 HwmpRtableTest::HwmpRtableTest () : |
292 result(true), |
301 Test ("Mesh/802.11s/HwmpRtable"), result (true), dst ("01:00:00:01:00:01"), hop ("01:00:00:01:00:03"), |
293 dst ("01:00:00:01:00:01"), |
302 iface (8010), metric (10), seqnum (1), expire (Seconds (10)) |
294 hop ("01:00:00:01:00:03"), |
|
295 iface (8010), |
|
296 metric (10), |
|
297 seqnum (1), |
|
298 expire (Seconds (10)) |
|
299 { |
303 { |
300 precursors.push_back (Mac48Address ("00:10:20:30:40:50")); |
304 precursors.push_back (Mac48Address ("00:10:20:30:40:50")); |
301 precursors.push_back (Mac48Address ("00:11:22:33:44:55")); |
305 precursors.push_back (Mac48Address ("00:11:22:33:44:55")); |
302 precursors.push_back (Mac48Address ("00:01:02:03:04:05")); |
306 precursors.push_back (Mac48Address ("00:01:02:03:04:05")); |
303 } |
307 } |
304 void HwmpRtableTest::TestLookup () |
308 void |
|
309 HwmpRtableTest::TestLookup () |
305 { |
310 { |
306 HwmpRtable::LookupResult correct (hop, iface, metric, seqnum); |
311 HwmpRtable::LookupResult correct (hop, iface, metric, seqnum); |
307 |
312 |
308 // Reactive path |
313 // Reactive path |
309 table->AddReactivePath (dst, hop, iface, metric, expire, seqnum); |
314 table->AddReactivePath (dst, hop, iface, metric, expire, seqnum); |
310 NS_TEST_ASSERT (table->LookupReactive (dst) == correct); |
315 NS_TEST_ASSERT (table->LookupReactive (dst) == correct); |
311 table->DeleteReactivePath (dst); |
316 table->DeleteReactivePath (dst); |
312 NS_TEST_ASSERT (! table->LookupReactive (dst).IsValid ()); |
317 NS_TEST_ASSERT (!table->LookupReactive (dst).IsValid ()); |
313 |
318 |
314 // Proactive |
319 // Proactive |
315 table->AddProactivePath (metric, dst, hop, iface, expire, seqnum); |
320 table->AddProactivePath (metric, dst, hop, iface, expire, seqnum); |
316 NS_TEST_ASSERT (table->LookupProactive () == correct); |
321 NS_TEST_ASSERT (table->LookupProactive () == correct); |
317 table->DeleteProactivePath (dst); |
322 table->DeleteProactivePath (dst); |
318 NS_TEST_ASSERT (! table->LookupProactive ().IsValid ()); |
323 NS_TEST_ASSERT (!table->LookupProactive ().IsValid ()); |
319 } |
324 } |
320 void HwmpRtableTest::TestAddPath () |
325 void |
|
326 HwmpRtableTest::TestAddPath () |
321 { |
327 { |
322 table->AddReactivePath (dst, hop, iface, metric, expire, seqnum); |
328 table->AddReactivePath (dst, hop, iface, metric, expire, seqnum); |
323 table->AddProactivePath (metric, dst, hop, iface, expire, seqnum); |
329 table->AddProactivePath (metric, dst, hop, iface, expire, seqnum); |
324 } |
330 } |
325 void HwmpRtableTest::TestExpire () |
331 void |
|
332 HwmpRtableTest::TestExpire () |
326 { |
333 { |
327 // this is assumed to be called when path records are already expired |
334 // this is assumed to be called when path records are already expired |
328 HwmpRtable::LookupResult correct (hop, iface, metric, seqnum); |
335 HwmpRtable::LookupResult correct (hop, iface, metric, seqnum); |
329 NS_TEST_ASSERT (table->LookupReactiveExpired (dst) == correct); |
336 NS_TEST_ASSERT (table->LookupReactiveExpired (dst) == correct); |
330 NS_TEST_ASSERT (table->LookupProactiveExpired () == correct); |
337 NS_TEST_ASSERT (table->LookupProactiveExpired () == correct); |
331 |
338 |
332 NS_TEST_ASSERT (! table->LookupReactive (dst).IsValid ()); |
339 NS_TEST_ASSERT (!table->LookupReactive (dst).IsValid ()); |
333 NS_TEST_ASSERT (! table->LookupProactive ().IsValid ()); |
340 NS_TEST_ASSERT (!table->LookupProactive ().IsValid ()); |
334 } |
341 } |
335 void HwmpRtableTest::TestPrecursorAdd () |
342 void |
336 { |
343 HwmpRtableTest::TestPrecursorAdd () |
337 for (std::vector<Mac48Address>::const_iterator i = precursors.begin (); i != precursors.end (); i ++) |
344 { |
338 { |
345 for (std::vector<Mac48Address>::const_iterator i = precursors.begin (); i != precursors.end (); i++) |
339 table->AddPrecursor (dst, iface, *i); |
346 { |
340 // Check that duplicates are filtered |
347 table->AddPrecursor (dst, iface, *i); |
341 table->AddPrecursor (dst, iface, *i); |
348 // Check that duplicates are filtered |
342 } |
349 table->AddPrecursor (dst, iface, *i); |
343 } |
350 } |
344 void HwmpRtableTest::TestPrecursorFind () |
351 } |
|
352 void |
|
353 HwmpRtableTest::TestPrecursorFind () |
345 { |
354 { |
346 HwmpRtable::PrecursorList precursorList = table->GetPrecursors (dst); |
355 HwmpRtable::PrecursorList precursorList = table->GetPrecursors (dst); |
347 NS_TEST_ASSERT(precursors.size () == precursorList.size ()); |
356 NS_TEST_ASSERT (precursors.size () == precursorList.size ()); |
348 for(unsigned int i = 0; i < precursors.size (); i ++) |
357 for (unsigned int i = 0; i < precursors.size (); i++) |
349 { |
358 { |
350 NS_TEST_ASSERT(precursorList[i].first == iface); |
359 NS_TEST_ASSERT (precursorList[i].first == iface); |
351 NS_TEST_ASSERT(precursorList[i].second == precursors[i]); |
360 NS_TEST_ASSERT (precursorList[i].second == precursors[i]); |
352 } |
361 } |
353 } |
362 } |
354 bool HwmpRtableTest::RunTests () |
363 bool |
|
364 HwmpRtableTest::RunTests () |
355 { |
365 { |
356 table = CreateObject<HwmpRtable> (); |
366 table = CreateObject<HwmpRtable> (); |
357 |
367 |
358 Simulator::Schedule (Seconds (0), & HwmpRtableTest::TestLookup, this); |
368 Simulator::Schedule (Seconds (0), &HwmpRtableTest::TestLookup, this); |
359 Simulator::Schedule (Seconds (1), & HwmpRtableTest::TestAddPath, this); |
369 Simulator::Schedule (Seconds (1), &HwmpRtableTest::TestAddPath, this); |
360 Simulator::Schedule (Seconds (2), & HwmpRtableTest::TestPrecursorAdd, this); |
370 Simulator::Schedule (Seconds (2), &HwmpRtableTest::TestPrecursorAdd, this); |
361 Simulator::Schedule (expire + Seconds (2), & HwmpRtableTest::TestExpire, this); |
371 Simulator::Schedule (expire + Seconds (2), &HwmpRtableTest::TestExpire, this); |
362 Simulator::Schedule (expire + Seconds (3), & HwmpRtableTest::TestPrecursorFind, this); |
372 Simulator::Schedule (expire + Seconds (3), &HwmpRtableTest::TestPrecursorFind, this); |
363 |
373 |
364 Simulator::Run (); |
374 Simulator::Run (); |
365 Simulator::Destroy (); |
375 Simulator::Destroy (); |
366 |
376 |
367 return result; |
377 return result; |
368 } |
378 } |
369 #endif // RUN_SELF_TESTS |
379 #endif // RUN_SELF_TESTS |
370 } //namespace dot11s |
380 } //namespace dot11s |
371 } //namespace ns3 |
381 } //namespace ns3 |