OLD | NEW |
| (Empty) |
1 // -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- | |
2 // | |
3 // Copyright (c) 2006 Georgia Tech Research Corporation | |
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: George F. Riley<riley@ece.gatech.edu> | |
19 // Gustavo Carneiro <gjc@inescporto.pt> | |
20 | |
21 #include "ns3/log.h" | |
22 #include "ipv4-static-routing.h" | |
23 #include "ns3/packet.h" | |
24 | |
25 NS_LOG_COMPONENT_DEFINE ("Ipv4StaticRouting"); | |
26 | |
27 namespace ns3 { | |
28 | |
29 Ipv4StaticRouting::Ipv4StaticRouting ()· | |
30 : m_defaultRoute (0), m_defaultMulticastRoute (0) | |
31 { | |
32 NS_LOG_FUNCTION_NOARGS (); | |
33 } | |
34 | |
35 void· | |
36 Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,· | |
37 Ipv4Address nextHop,· | |
38 uint32_t interface) | |
39 { | |
40 NS_LOG_FUNCTION_NOARGS (); | |
41 Ipv4Route *route = new Ipv4Route (); | |
42 *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface); | |
43 m_hostRoutes.push_back (route); | |
44 } | |
45 | |
46 void· | |
47 Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,· | |
48 uint32_t interface) | |
49 { | |
50 NS_LOG_FUNCTION_NOARGS (); | |
51 Ipv4Route *route = new Ipv4Route (); | |
52 *route = Ipv4Route::CreateHostRouteTo (dest, interface); | |
53 m_hostRoutes.push_back (route); | |
54 } | |
55 | |
56 void· | |
57 Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,· | |
58 Ipv4Mask networkMask,· | |
59 Ipv4Address nextHop,· | |
60 uint32_t interface) | |
61 { | |
62 NS_LOG_FUNCTION_NOARGS (); | |
63 Ipv4Route *route = new Ipv4Route (); | |
64 *route = Ipv4Route::CreateNetworkRouteTo (network, | |
65 networkMask, | |
66 nextHop, | |
67 interface); | |
68 m_networkRoutes.push_back (route); | |
69 } | |
70 | |
71 void· | |
72 Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,· | |
73 Ipv4Mask networkMask,· | |
74 uint32_t interface) | |
75 { | |
76 NS_LOG_FUNCTION_NOARGS (); | |
77 Ipv4Route *route = new Ipv4Route (); | |
78 *route = Ipv4Route::CreateNetworkRouteTo (network, | |
79 networkMask, | |
80 interface); | |
81 m_networkRoutes.push_back (route); | |
82 } | |
83 | |
84 void· | |
85 Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop,· | |
86 uint32_t interface) | |
87 { | |
88 NS_LOG_FUNCTION_NOARGS (); | |
89 Ipv4Route *route = new Ipv4Route (); | |
90 *route = Ipv4Route::CreateDefaultRoute (nextHop, interface); | |
91 delete m_defaultRoute; | |
92 m_defaultRoute = route; | |
93 } | |
94 | |
95 void· | |
96 Ipv4StaticRouting::AddMulticastRoute(Ipv4Address origin, | |
97 Ipv4Address group, | |
98 uint32_t inputInterface, | |
99 std::vector<uint32_t> outputInterfaces) | |
100 { | |
101 NS_LOG_FUNCTION_NOARGS (); | |
102 Ipv4MulticastRoute *route = new Ipv4MulticastRoute (); | |
103 *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group,· | |
104 inputInterface, outputInterfaces); | |
105 m_multicastRoutes.push_back (route); | |
106 } | |
107 | |
108 void· | |
109 Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface) | |
110 { | |
111 NS_LOG_FUNCTION_NOARGS (); | |
112 Ipv4Address origin = Ipv4Address::GetAny (); | |
113 Ipv4Address group = Ipv4Address::GetAny (); | |
114 uint32_t inputInterface = Ipv4RoutingProtocol::INTERFACE_ANY; | |
115 | |
116 std::vector<uint32_t> outputInterfaces (1); | |
117 outputInterfaces[0] = outputInterface; | |
118 ·· | |
119 Ipv4MulticastRoute *route = new Ipv4MulticastRoute (); | |
120 *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group,· | |
121 inputInterface, outputInterfaces); | |
122 | |
123 delete m_defaultMulticastRoute; | |
124 m_defaultMulticastRoute = route; | |
125 } | |
126 | |
127 uint32_t· | |
128 Ipv4StaticRouting::GetNMulticastRoutes (void) const | |
129 { | |
130 NS_LOG_FUNCTION_NOARGS (); | |
131 return m_multicastRoutes.size () + m_defaultMulticastRoute ? 1 : 0; | |
132 } | |
133 | |
134 Ipv4MulticastRoute * | |
135 Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const | |
136 { | |
137 NS_LOG_FUNCTION_NOARGS (); | |
138 NS_ASSERT_MSG(index < m_multicastRoutes.size (), | |
139 "Ipv4StaticRouting::GetMulticastRoute (): Index out of range"); | |
140 // | |
141 // From an external point of view the default route appears to be in slot 0 | |
142 // of the routing table. The implementation, however, puts it in a separate· | |
143 // place. So, if a client asks for index 0 and we have a default multicast | |
144 // route, we have to return it from that different place· | |
145 // (m_defaultMulticastRoute). | |
146 // | |
147 if (index == 0 && m_defaultMulticastRoute != 0) | |
148 { | |
149 return m_defaultMulticastRoute; | |
150 } | |
151 // | |
152 // If there is a default multicast route present, a client will just assume | |
153 // that it is in slot zero and there is one "extra" zeroth route in the table. | |
154 // To return the correct indexed entry in our list, we have to decrement the | |
155 // index to take into account the default route not being in the actual list. | |
156 // Since we fell through to here, we've taken care of the case where the | |
157 // index was zero. | |
158 // | |
159 if (m_defaultMulticastRoute != 0) | |
160 { | |
161 NS_ASSERT(index > 0); | |
162 index--; | |
163 } | |
164 | |
165 if (index < m_multicastRoutes.size ()) | |
166 { | |
167 uint32_t tmp = 0; | |
168 for (MulticastRoutesCI i = m_multicastRoutes.begin ();· | |
169 i != m_multicastRoutes.end ();· | |
170 i++)· | |
171 { | |
172 if (tmp == index) | |
173 { | |
174 return *i; | |
175 } | |
176 tmp++; | |
177 } | |
178 } | |
179 return 0; | |
180 } | |
181 | |
182 Ipv4MulticastRoute * | |
183 Ipv4StaticRouting::GetDefaultMulticastRoute () const | |
184 { | |
185 NS_LOG_FUNCTION_NOARGS (); | |
186 if (m_defaultMulticastRoute != 0) | |
187 { | |
188 return m_defaultMulticastRoute; | |
189 } | |
190 return 0; | |
191 } | |
192 | |
193 bool | |
194 Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin, | |
195 Ipv4Address group, | |
196 uint32_t inputInterface) | |
197 { | |
198 NS_LOG_FUNCTION_NOARGS (); | |
199 for (MulticastRoutesI i = m_multicastRoutes.begin ();· | |
200 i != m_multicastRoutes.end ();· | |
201 i++)· | |
202 { | |
203 Ipv4MulticastRoute *route = *i; | |
204 if (origin == route->GetOrigin () && | |
205 group == route->GetGroup () && | |
206 inputInterface == route->GetInputInterface ()) | |
207 { | |
208 delete *i; | |
209 m_multicastRoutes.erase (i); | |
210 return true; | |
211 } | |
212 } | |
213 return false; | |
214 } | |
215 | |
216 void· | |
217 Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index) | |
218 { | |
219 NS_LOG_FUNCTION_NOARGS (); | |
220 // | |
221 // From an external point of view the default route appears to be in slot 0 | |
222 // of the routing table. The implementation, however, puts it in a separate· | |
223 // place. So, if a client asks to delete index 0 and we have a default | |
224 // multicast route set, we have to delete it from that different place· | |
225 // (m_defaultMulticastRoute). | |
226 // | |
227 if (index == 0 && m_defaultMulticastRoute != 0) | |
228 { | |
229 delete m_defaultMulticastRoute; | |
230 m_defaultMulticastRoute = 0; | |
231 } | |
232 // | |
233 // If there is a default multicast route present, a client will just assume | |
234 // that it is in slot zero and there is one "extra" zeroth route in the table. | |
235 // To return the correct indexed entry in our list, we have to decrement the | |
236 // index to take into account the default route not being in the actual list. | |
237 // Since we fell through to here, we've taken care of the case where the | |
238 // index was zero. | |
239 // | |
240 if (m_defaultMulticastRoute != 0) | |
241 { | |
242 NS_ASSERT(index > 0); | |
243 index--; | |
244 } | |
245 | |
246 uint32_t tmp = 0; | |
247 for (MulticastRoutesI i = m_multicastRoutes.begin ();· | |
248 i != m_multicastRoutes.end ();· | |
249 i++)· | |
250 { | |
251 if (tmp == index) | |
252 { | |
253 delete *i; | |
254 m_multicastRoutes.erase (i); | |
255 return; | |
256 } | |
257 tmp++; | |
258 } | |
259 } | |
260 | |
261 Ipv4Route * | |
262 Ipv4StaticRouting::LookupStatic (Ipv4Address dest) | |
263 { | |
264 NS_LOG_FUNCTION_NOARGS (); | |
265 for (HostRoutesCI i = m_hostRoutes.begin ();· | |
266 i != m_hostRoutes.end ();· | |
267 i++)· | |
268 { | |
269 NS_ASSERT ((*i)->IsHost ()); | |
270 if ((*i)->GetDest ().IsEqual (dest))· | |
271 { | |
272 return (*i); | |
273 } | |
274 } | |
275 for (NetworkRoutesI j = m_networkRoutes.begin ();· | |
276 j != m_networkRoutes.end ();· | |
277 j++)· | |
278 { | |
279 NS_ASSERT ((*j)->IsNetwork ()); | |
280 Ipv4Mask mask = (*j)->GetDestNetworkMask (); | |
281 Ipv4Address entry = (*j)->GetDestNetwork (); | |
282 if (mask.IsMatch (dest, entry))· | |
283 { | |
284 return (*j); | |
285 } | |
286 } | |
287 if (m_defaultRoute != 0)· | |
288 { | |
289 NS_ASSERT (m_defaultRoute->IsDefault ()); | |
290 return m_defaultRoute; | |
291 } | |
292 return 0; | |
293 } | |
294 | |
295 Ipv4MulticastRoute * | |
296 Ipv4StaticRouting::LookupStatic ( | |
297 Ipv4Address origin,· | |
298 Ipv4Address group, | |
299 uint32_t interface) | |
300 { | |
301 NS_LOG_FUNCTION_NOARGS (); | |
302 // | |
303 // We treat the "any" address (typically 0.0.0.0) as a wildcard in our matching | |
304 // scheme. | |
305 // | |
306 Ipv4Address wildcard = Ipv4Address::GetAny (); | |
307 | |
308 for (MulticastRoutesI i = m_multicastRoutes.begin ();· | |
309 i != m_multicastRoutes.end ();· | |
310 i++)· | |
311 { | |
312 Ipv4MulticastRoute *route = *i; | |
313 // | |
314 // We've been passed an origin address, a multicast group address and an· | |
315 // interface index. We have to decide if the current route in the list is | |
316 // a match. | |
317 // | |
318 // The first case is the restrictive case where the origin, group and index | |
319 // matches. This picks up exact routes during forwarded and exact routes from | |
320 // the local node (in which case the interface is a wildcard). | |
321 // | |
322 if (origin == route->GetOrigin () && group == route->GetGroup ()) | |
323 { | |
324 if (interface == Ipv4RoutingProtocol::INTERFACE_ANY ||· | |
325 interface == route->GetInputInterface ()) | |
326 { | |
327 return *i; | |
328 } | |
329 } | |
330 } | |
331 // | |
332 // If the input interface index is not a wildcard (that means that the packet· | |
333 // did not originally come from this node), we're done. We don't | |
334 // just happily forward packets we don't really know what to do with.·· | |
335 // Multicast storms are not generally considered a good thing. | |
336 // | |
337 if (interface != Ipv4RoutingProtocol::INTERFACE_ANY) | |
338 { | |
339 return 0; | |
340 } | |
341 // | |
342 // Now, we're going to get a litle less restricive. This only applies in the | |
343 // case where the packet in question is coming from the local node. In order | |
344 // to avoid dependencies on the order in which routes were added, we will· | |
345 // actually walk the list two more times, the first time looking for routes | |
346 // with a single wildcard, and the last time looking for the first route | |
347 // with two wildcards. | |
348 // | |
349 for (MulticastRoutesI i = m_multicastRoutes.begin ();· | |
350 i != m_multicastRoutes.end ();· | |
351 i++)· | |
352 { | |
353 Ipv4MulticastRoute *route = *i; | |
354 // | |
355 // Here we will ignore the origin. We know that a single source address must | |
356 // be picked for a packet, but we may want to send multicast packets out | |
357 // multiple interfaces. To support this case, a user would need to add | |
358 // a Multicast route with the route's origin set to wildcard. N.B As a | |
359 // result, packets sourced from a node with multiple interface may have a | |
360 // source IP address different from that of the interface actually used to | |
361 // send the packet. | |
362 // | |
363 if (route->GetOrigin () == wildcard && group == route->GetGroup ()) | |
364 { | |
365 return *i; | |
366 } | |
367 } | |
368 // | |
369 // Finally we want to allow users to specify a default route that specifies | |
370 // sending all multicast packets out multiple interfaces. The standard | |
371 // default multicast route is patterned after other systems and limits the· | |
372 // number of outputs to one. If, however a client manually adds a multicast | |
373 // route with the origin, the multicast group and the input interface index | |
374 // all set to wildcard, she has created a default route with multiple output | |
375 // interfaces. | |
376 // | |
377 for (MulticastRoutesI i = m_multicastRoutes.begin ();· | |
378 i != m_multicastRoutes.end ();· | |
379 i++)· | |
380 { | |
381 Ipv4MulticastRoute *route = *i; | |
382 | |
383 if (route->GetOrigin () == wildcard && route->GetGroup () == wildcard) | |
384 { | |
385 return *i; | |
386 } | |
387 } | |
388 // | |
389 // We also allow users to specify a typical default multicast route. This | |
390 // default route is limited to specifying a single output interface. | |
391 // | |
392 if (m_defaultMulticastRoute != 0)· | |
393 { | |
394 return m_defaultMulticastRoute; | |
395 } | |
396 | |
397 return 0; | |
398 } | |
399 | |
400 uint32_t· | |
401 Ipv4StaticRouting::GetNRoutes (void) | |
402 { | |
403 NS_LOG_FUNCTION_NOARGS (); | |
404 uint32_t n = 0; | |
405 if (m_defaultRoute != 0) | |
406 { | |
407 n++; | |
408 } | |
409 n += m_hostRoutes.size (); | |
410 n += m_networkRoutes.size (); | |
411 return n; | |
412 } | |
413 | |
414 Ipv4Route * | |
415 Ipv4StaticRouting::GetDefaultRoute () | |
416 { | |
417 NS_LOG_FUNCTION_NOARGS (); | |
418 if (m_defaultRoute != 0) | |
419 { | |
420 return m_defaultRoute; | |
421 } | |
422 else | |
423 { | |
424 return 0; | |
425 } | |
426 } | |
427 | |
428 Ipv4Route * | |
429 Ipv4StaticRouting::GetRoute (uint32_t index) | |
430 { | |
431 NS_LOG_FUNCTION_NOARGS (); | |
432 if (index == 0 && m_defaultRoute != 0) | |
433 { | |
434 return m_defaultRoute; | |
435 } | |
436 if (index > 0 && m_defaultRoute != 0) | |
437 { | |
438 index--; | |
439 } | |
440 if (index < m_hostRoutes.size ()) | |
441 { | |
442 uint32_t tmp = 0; | |
443 for (HostRoutesCI i = m_hostRoutes.begin ();· | |
444 i != m_hostRoutes.end ();· | |
445 i++)· | |
446 { | |
447 if (tmp == index) | |
448 { | |
449 return *i; | |
450 } | |
451 tmp++; | |
452 } | |
453 } | |
454 index -= m_hostRoutes.size (); | |
455 uint32_t tmp = 0; | |
456 for (NetworkRoutesI j = m_networkRoutes.begin ();· | |
457 j != m_networkRoutes.end ();· | |
458 j++)· | |
459 { | |
460 if (tmp == index) | |
461 { | |
462 return *j; | |
463 } | |
464 tmp++; | |
465 } | |
466 NS_ASSERT (false); | |
467 // quiet compiler. | |
468 return 0; | |
469 } | |
470 void· | |
471 Ipv4StaticRouting::RemoveRoute (uint32_t index) | |
472 { | |
473 NS_LOG_FUNCTION_NOARGS (); | |
474 if (index == 0 && m_defaultRoute != 0) | |
475 { | |
476 delete m_defaultRoute; | |
477 m_defaultRoute = 0; | |
478 } | |
479 if (index > 0 && m_defaultRoute != 0) | |
480 { | |
481 index--; | |
482 } | |
483 if (index < m_hostRoutes.size ()) | |
484 { | |
485 uint32_t tmp = 0; | |
486 for (HostRoutesI i = m_hostRoutes.begin ();· | |
487 i != m_hostRoutes.end ();· | |
488 i++)· | |
489 { | |
490 if (tmp == index) | |
491 { | |
492 delete *i; | |
493 m_hostRoutes.erase (i); | |
494 return; | |
495 } | |
496 tmp++; | |
497 } | |
498 } | |
499 index -= m_hostRoutes.size (); | |
500 uint32_t tmp = 0; | |
501 for (NetworkRoutesI j = m_networkRoutes.begin ();· | |
502 j != m_networkRoutes.end ();· | |
503 j++)· | |
504 { | |
505 if (tmp == index) | |
506 { | |
507 delete *j; | |
508 m_networkRoutes.erase (j); | |
509 return; | |
510 } | |
511 tmp++; | |
512 } | |
513 NS_ASSERT (false); | |
514 } | |
515 | |
516 bool | |
517 Ipv4StaticRouting::RequestRoute ( | |
518 uint32_t interface, | |
519 Ipv4Header const &ipHeader, | |
520 Ptr<Packet> packet, | |
521 RouteReplyCallback routeReply) | |
522 { | |
523 NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply); | |
524 | |
525 NS_LOG_LOGIC ("source = " << ipHeader.GetSource ()); | |
526 | |
527 NS_LOG_LOGIC ("destination = " << ipHeader.GetDestination ()); | |
528 | |
529 if (ipHeader.GetDestination ().IsMulticast ()) | |
530 { | |
531 NS_LOG_LOGIC ("Multicast destination"); | |
532 | |
533 Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), | |
534 ipHeader.GetDestination (), interface); | |
535 | |
536 if (mRoute) | |
537 { | |
538 NS_LOG_LOGIC ("Multicast route found"); | |
539 | |
540 for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) | |
541 { | |
542 Ptr<Packet> p = packet->Copy (); | |
543 Ipv4Header h = ipHeader; | |
544 Ipv4Route route =· | |
545 Ipv4Route::CreateHostRouteTo(h.GetDestination (),· | |
546 mRoute->GetOutputInterface(i)); | |
547 NS_LOG_LOGIC ( "Send via interface " <<· | |
548 mRoute->GetOutputInterface(i)); | |
549 routeReply (true, route, p, h); | |
550 } | |
551 return true; | |
552 } | |
553 return false; // Let other routing protocols try to handle this | |
554 } | |
555 // | |
556 // This is a unicast packet. Check to see if we have a route for it. | |
557 // | |
558 NS_LOG_LOGIC ("Unicast destination"); | |
559 Ipv4Route *route = LookupStatic (ipHeader.GetDestination ()); | |
560 if (route != 0) | |
561 { | |
562 routeReply (true, *route, packet, ipHeader); | |
563 return true; | |
564 } | |
565 else | |
566 { | |
567 return false; // Let other routing protocols try to handle this | |
568 // route request. | |
569 } | |
570 } | |
571 | |
572 bool | |
573 Ipv4StaticRouting::RequestInterface (Ipv4Address destination, uint32_t& interfac
e) | |
574 { | |
575 NS_LOG_FUNCTION (this << destination << &interface); | |
576 // | |
577 // First, see if this is a multicast packet we have a route for. If we | |
578 // have a route, then send the packet down each of the specified interfaces. | |
579 // | |
580 if (destination.IsMulticast ()) | |
581 { | |
582 NS_LOG_LOGIC ("Multicast destination"); | |
583 | |
584 Ipv4MulticastRoute *mRoute = LookupStatic(Ipv4Address::GetAny (), | |
585 destination, Ipv4RoutingProtocol::INTERFACE_ANY); | |
586 | |
587 if (mRoute) | |
588 { | |
589 NS_LOG_LOGIC ("Multicast route found"); | |
590 | |
591 if (mRoute->GetNOutputInterfaces () != 1) | |
592 { | |
593 NS_LOG_LOGIC ("Route is to multiple interfaces. Ignoring."); | |
594 return false; | |
595 } | |
596 | |
597 interface = mRoute->GetOutputInterface(0); | |
598 NS_LOG_LOGIC ("Found interface " << interface); | |
599 return true; | |
600 } | |
601 return false; // Let other routing protocols try to handle this | |
602 } | |
603 // | |
604 // See if this is a unicast packet we have a route for. | |
605 // | |
606 NS_LOG_LOGIC ("Unicast destination"); | |
607 Ipv4Route *route = LookupStatic (destination); | |
608 if (route) | |
609 { | |
610 interface = route->GetInterface (); | |
611 return true; | |
612 } | |
613 else | |
614 { | |
615 return false; | |
616 } | |
617 } | |
618 | |
619 void | |
620 Ipv4StaticRouting::DoDispose (void) | |
621 { | |
622 NS_LOG_FUNCTION_NOARGS (); | |
623 for (HostRoutesI i = m_hostRoutes.begin ();· | |
624 i != m_hostRoutes.end ();· | |
625 i = m_hostRoutes.erase (i))· | |
626 { | |
627 delete (*i); | |
628 } | |
629 for (NetworkRoutesI j = m_networkRoutes.begin ();· | |
630 j != m_networkRoutes.end ();· | |
631 j = m_networkRoutes.erase (j))· | |
632 { | |
633 delete (*j); | |
634 } | |
635 if (m_defaultRoute != 0) | |
636 { | |
637 delete m_defaultRoute; | |
638 m_defaultRoute = 0; | |
639 } | |
640 for (MulticastRoutesI i = m_multicastRoutes.begin ();· | |
641 i != m_multicastRoutes.end ();· | |
642 i = m_multicastRoutes.erase (i))· | |
643 { | |
644 delete (*i); | |
645 } | |
646 if (m_defaultMulticastRoute != 0) | |
647 { | |
648 delete m_defaultMulticastRoute; | |
649 m_defaultMulticastRoute = 0; | |
650 } | |
651 Ipv4RoutingProtocol::DoDispose (); | |
652 } | |
653 | |
654 }//namespace ns3 | |
OLD | NEW |