1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2004 Francisco J. Ros |
|
4 * Copyright (c) 2007 INESC Porto |
|
5 * |
|
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 |
|
8 * published by the Free Software Foundation; |
|
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, write to the Free Software |
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 * |
|
19 * Authors: Francisco J. Ros <fjrm@dif.um.es> |
|
20 * Gustavo J. A. M. Carneiro <gjc@inescporto.pt> |
|
21 */ |
|
22 |
|
23 /// |
|
24 /// \file OLSR_rtable.cc |
|
25 /// \brief Implementation of our routing table. |
|
26 /// |
|
27 |
|
28 #include "olsr-routing-table.h" |
|
29 #include "ns3/packet.h" |
|
30 #include "ns3/ipv4-header.h" |
|
31 #include "ns3/log.h" |
|
32 |
|
33 namespace ns3 { namespace olsr { |
|
34 |
|
35 NS_LOG_COMPONENT_DEFINE ("OlsrRoutingTable"); |
|
36 |
|
37 /// |
|
38 /// \brief Clears the routing table and frees the memory assigned to each one of its entries. |
|
39 /// |
|
40 void |
|
41 RoutingTable::Clear () |
|
42 { |
|
43 NS_LOG_FUNCTION_NOARGS (); |
|
44 m_table.clear (); |
|
45 } |
|
46 |
|
47 /// |
|
48 /// \brief Deletes the entry whose destination address is given. |
|
49 /// \param dest address of the destination node. |
|
50 /// |
|
51 void |
|
52 RoutingTable::RemoveEntry (Ipv4Address const &dest) |
|
53 { |
|
54 m_table.erase (dest); |
|
55 } |
|
56 |
|
57 /// |
|
58 /// \brief Looks up an entry for the specified destination address. |
|
59 /// \param dest destination address. |
|
60 /// \param outEntry output parameter to hold the routing entry result, if fuond |
|
61 /// \return true if found, false if not found |
|
62 /// |
|
63 bool |
|
64 RoutingTable::Lookup (Ipv4Address const &dest, |
|
65 RoutingTableEntry &outEntry) const |
|
66 { |
|
67 // Get the iterator at "dest" position |
|
68 std::map<Ipv4Address, RoutingTableEntry>::const_iterator it = |
|
69 m_table.find (dest); |
|
70 // If there is no route to "dest", return NULL |
|
71 if (it == m_table.end ()) |
|
72 return false; |
|
73 outEntry = it->second; |
|
74 return true; |
|
75 } |
|
76 |
|
77 /// |
|
78 /// \brief Finds the appropiate entry which must be used in order to forward |
|
79 /// a data packet to a next hop (given a destination). |
|
80 /// |
|
81 /// Imagine a routing table like this: [A,B] [B,C] [C,C]; being each pair of the |
|
82 /// form [dest addr,next-hop addr]. In this case, if this function is invoked with |
|
83 /// [A,B] then pair [C,C] is returned because C is the next hop that must be used |
|
84 /// to forward a data packet destined to A. That is, C is a neighbor of this node, |
|
85 /// but B isn't. This function finds the appropiate neighbor for forwarding a packet. |
|
86 /// |
|
87 /// \param entry the routing table entry which indicates the destination node |
|
88 /// we are interested in. |
|
89 /// \return the appropiate routing table entry which indicates the next |
|
90 /// hop which must be used for forwarding a data packet, or NULL |
|
91 /// if there is no such entry. |
|
92 /// |
|
93 bool |
|
94 RoutingTable::FindSendEntry (RoutingTableEntry const &entry, |
|
95 RoutingTableEntry &outEntry) const |
|
96 { |
|
97 outEntry = entry; |
|
98 while (outEntry.destAddr != outEntry.nextAddr) |
|
99 { |
|
100 if (not Lookup(outEntry.nextAddr, outEntry)) |
|
101 return false; |
|
102 } |
|
103 return true; |
|
104 } |
|
105 |
|
106 |
|
107 bool |
|
108 RoutingTable::RequestRoute (uint32_t ifIndex, |
|
109 const Ipv4Header &ipHeader, |
|
110 Ptr<Packet> packet, |
|
111 RouteReplyCallback routeReply) |
|
112 { |
|
113 RoutingTableEntry entry1, entry2; |
|
114 if (Lookup (ipHeader.GetDestination (), entry1)) |
|
115 { |
|
116 bool foundSendEntry = FindSendEntry (entry1, entry2); |
|
117 if (!foundSendEntry) |
|
118 NS_FATAL_ERROR ("FindSendEntry failure"); |
|
119 |
|
120 Ipv4Route route = Ipv4Route::CreateHostRouteTo |
|
121 (ipHeader.GetDestination (), entry2.nextAddr, entry2.interface); |
|
122 |
|
123 NS_LOG_DEBUG ("Olsr node " << m_mainAddress |
|
124 << ": RouteRequest for dest=" << ipHeader.GetDestination () |
|
125 << " --> nestHop=" << entry2.nextAddr |
|
126 << " interface=" << entry2.interface); |
|
127 |
|
128 routeReply (true, route, packet, ipHeader); |
|
129 return true; |
|
130 } |
|
131 else |
|
132 { |
|
133 #ifdef NS3_LOG_ENABLE |
|
134 NS_LOG_DEBUG ("Olsr node " << m_mainAddress |
|
135 << ": RouteRequest for dest=" << ipHeader.GetDestination () |
|
136 << " --> NOT FOUND; ** Dumping routing table..."); |
|
137 for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator iter = m_table.begin (); |
|
138 iter != m_table.end (); iter++) |
|
139 { |
|
140 NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr |
|
141 << " via interface " << iter->second.interface); |
|
142 } |
|
143 |
|
144 NS_LOG_DEBUG ("** Routing table dump end."); |
|
145 #endif |
|
146 return false; |
|
147 } |
|
148 } |
|
149 |
|
150 bool |
|
151 RoutingTable::RequestIfIndex (Ipv4Address destination, |
|
152 uint32_t& ifIndex) |
|
153 { |
|
154 RoutingTableEntry entry1, entry2; |
|
155 if (Lookup (destination, entry1)) |
|
156 { |
|
157 bool foundSendEntry = FindSendEntry (entry1, entry2); |
|
158 if (!foundSendEntry) |
|
159 NS_FATAL_ERROR ("FindSendEntry failure"); |
|
160 ifIndex = entry2.interface; |
|
161 return true; |
|
162 } |
|
163 else |
|
164 { |
|
165 return false; |
|
166 } |
|
167 } |
|
168 |
|
169 |
|
170 /// |
|
171 /// \brief Adds a new entry into the routing table. |
|
172 /// |
|
173 /// If an entry for the given destination existed, it is deleted and freed. |
|
174 /// |
|
175 /// \param dest address of the destination node. |
|
176 /// \param next address of the next hop node. |
|
177 /// \param iface address of the local interface. |
|
178 /// \param dist distance to the destination node. |
|
179 /// |
|
180 void |
|
181 RoutingTable::AddEntry (Ipv4Address const &dest, |
|
182 Ipv4Address const &next, |
|
183 uint32_t interface, |
|
184 uint32_t distance) |
|
185 { |
|
186 NS_LOG_FUNCTION (this << dest << next << interface << distance << m_mainAddress); |
|
187 |
|
188 NS_ASSERT (distance > 0); |
|
189 |
|
190 // Creates a new rt entry with specified values |
|
191 RoutingTableEntry &entry = m_table[dest]; |
|
192 |
|
193 entry.destAddr = dest; |
|
194 entry.nextAddr = next; |
|
195 entry.interface = interface; |
|
196 entry.distance = distance; |
|
197 } |
|
198 |
|
199 void |
|
200 RoutingTable::AddEntry (Ipv4Address const &dest, |
|
201 Ipv4Address const &next, |
|
202 Ipv4Address const &interfaceAddress, |
|
203 uint32_t distance) |
|
204 { |
|
205 NS_LOG_FUNCTION (this << dest << next << interfaceAddress << distance << m_mainAddress); |
|
206 |
|
207 NS_ASSERT (distance > 0); |
|
208 NS_ASSERT (m_ipv4); |
|
209 |
|
210 RoutingTableEntry entry; |
|
211 for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++) |
|
212 { |
|
213 if (m_ipv4->GetAddress (i) == interfaceAddress) |
|
214 { |
|
215 AddEntry (dest, next, i, distance); |
|
216 return; |
|
217 } |
|
218 } |
|
219 NS_ASSERT (false); // should not be reached |
|
220 AddEntry (dest, next, 0, distance); |
|
221 } |
|
222 |
|
223 void |
|
224 RoutingTable::SetMainAddress (Ipv4Address mainAddress) |
|
225 { |
|
226 m_mainAddress = mainAddress; |
|
227 } |
|
228 |
|
229 void |
|
230 RoutingTable::SetIpv4 (Ptr<Ipv4> ipv4) |
|
231 { |
|
232 m_ipv4 = ipv4; |
|
233 } |
|
234 |
|
235 std::vector<RoutingTableEntry> |
|
236 RoutingTable::GetEntries () const |
|
237 { |
|
238 std::vector<RoutingTableEntry> retval; |
|
239 for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator iter = m_table.begin (); |
|
240 iter != m_table.end (); iter++) |
|
241 { |
|
242 retval.push_back (iter->second); |
|
243 } |
|
244 return retval; |
|
245 } |
|
246 |
|
247 /// |
|
248 /// \brief Returns the number of entries in the routing table. |
|
249 /// \return the number of entries in the routing table. |
|
250 /// |
|
251 // u_int32_t |
|
252 // RoutingTable::size() { |
|
253 // return rt_.size(); |
|
254 // } |
|
255 |
|
256 }}; // namespace ns3, olsr |
|
257 |
|
258 |
|
259 |
|
260 #ifdef RUN_SELF_TESTS |
|
261 |
|
262 |
|
263 #include "ns3/test.h" |
|
264 |
|
265 |
|
266 namespace ns3 { namespace olsr { |
|
267 |
|
268 class OlsrRoutingTableTest : public ns3::Test { |
|
269 private: |
|
270 public: |
|
271 OlsrRoutingTableTest (); |
|
272 virtual bool RunTests (void); |
|
273 |
|
274 |
|
275 }; |
|
276 |
|
277 OlsrRoutingTableTest::OlsrRoutingTableTest () |
|
278 : ns3::Test ("OlsrRoutingTable") |
|
279 {} |
|
280 |
|
281 |
|
282 bool |
|
283 OlsrRoutingTableTest::RunTests (void) |
|
284 { |
|
285 bool result = true; |
|
286 |
|
287 RoutingTable table; |
|
288 |
|
289 table.AddEntry (Ipv4Address ("1.2.3.5"), |
|
290 Ipv4Address ("1.2.3.4"), |
|
291 0, |
|
292 1); |
|
293 |
|
294 table.AddEntry (Ipv4Address ("1.2.3.4"), |
|
295 Ipv4Address ("1.2.3.4"), |
|
296 0, |
|
297 1); |
|
298 |
|
299 RoutingTableEntry entry1; |
|
300 NS_TEST_ASSERT (table.Lookup (Ipv4Address ("1.2.3.5"), entry1)); |
|
301 NS_TEST_ASSERT_EQUAL (entry1.destAddr, Ipv4Address ("1.2.3.5")); |
|
302 NS_TEST_ASSERT_EQUAL (entry1.nextAddr, Ipv4Address ("1.2.3.4")); |
|
303 NS_TEST_ASSERT_EQUAL (entry1.interface, 0); |
|
304 NS_TEST_ASSERT_EQUAL (entry1.distance, 1); |
|
305 |
|
306 RoutingTableEntry entry2; |
|
307 NS_TEST_ASSERT (table.Lookup (Ipv4Address ("1.2.3.4"), entry2)); |
|
308 NS_TEST_ASSERT_EQUAL (entry2.destAddr, Ipv4Address ("1.2.3.4")); |
|
309 NS_TEST_ASSERT_EQUAL (entry2.nextAddr, Ipv4Address ("1.2.3.4")); |
|
310 NS_TEST_ASSERT_EQUAL (entry2.interface, 0); |
|
311 NS_TEST_ASSERT_EQUAL (entry2.distance, 1); |
|
312 |
|
313 RoutingTableEntry sendEntry; |
|
314 NS_TEST_ASSERT (table.FindSendEntry (entry1, sendEntry)); |
|
315 NS_TEST_ASSERT_EQUAL (sendEntry.destAddr, Ipv4Address ("1.2.3.4")); |
|
316 NS_TEST_ASSERT_EQUAL (sendEntry.nextAddr, Ipv4Address ("1.2.3.4")); |
|
317 NS_TEST_ASSERT_EQUAL (sendEntry.interface, 0); |
|
318 NS_TEST_ASSERT_EQUAL (sendEntry.distance, 1); |
|
319 |
|
320 table.RemoveEntry (Ipv4Address ("1.2.3.5")); |
|
321 RoutingTableEntry removedEntry; |
|
322 NS_TEST_ASSERT (not table.Lookup (Ipv4Address ("1.2.3.5"), removedEntry)); |
|
323 |
|
324 return result; |
|
325 } |
|
326 |
|
327 static OlsrRoutingTableTest gOlsrRoutingTableTest; |
|
328 |
|
329 }}; // namespace |
|
330 |
|
331 |
|
332 #endif /* RUN_SELF_TESTS */ |
|