|
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 // |
|
20 |
|
21 #include "ns3/packet.h" |
|
22 #include "ns3/log.h" |
|
23 #include "ns3/callback.h" |
|
24 #include "ns3/ipv4-address.h" |
|
25 #include "ns3/ipv4-route.h" |
|
26 #include "ns3/node.h" |
|
27 #include "ns3/socket.h" |
|
28 #include "ns3/net-device.h" |
|
29 #include "ns3/uinteger.h" |
|
30 #include "ns3/trace-source-accessor.h" |
|
31 #include "ns3/object-vector.h" |
|
32 #include "ns3/ipv4-header.h" |
|
33 #include "ns3/boolean.h" |
|
34 #include "arp-l3-protocol.h" |
|
35 |
|
36 #include "ipv4-l3-protocol.h" |
|
37 #include "ipv4-l4-protocol.h" |
|
38 #include "ipv4-interface.h" |
|
39 #include "ipv4-loopback-interface.h" |
|
40 #include "arp-ipv4-interface.h" |
|
41 #include "ipv4-l4-demux.h" |
|
42 |
|
43 NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol"); |
|
44 |
|
45 namespace ns3 { |
|
46 |
|
47 const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800; |
|
48 |
|
49 NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol); |
|
50 |
|
51 TypeId |
|
52 Ipv4L3Protocol::GetTypeId (void) |
|
53 { |
|
54 static TypeId tid = TypeId ("ns3::Ipv4L3Protocol") |
|
55 .SetParent<Object> () |
|
56 .AddConstructor<Ipv4L3Protocol> () |
|
57 .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.", |
|
58 UintegerValue (64), |
|
59 MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl), |
|
60 MakeUintegerChecker<uint8_t> ()) |
|
61 .AddAttribute ("CalcChecksum", "If true, we calculate the checksum of outgoing packets" |
|
62 " and verify the checksum of incoming packets.", |
|
63 BooleanValue (false), |
|
64 MakeBooleanAccessor (&Ipv4L3Protocol::m_calcChecksum), |
|
65 MakeBooleanChecker ()) |
|
66 .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.", |
|
67 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace)) |
|
68 .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.", |
|
69 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace)) |
|
70 .AddTraceSource ("Drop", "Drop ipv4 packet", |
|
71 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace)) |
|
72 .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.", |
|
73 ObjectVectorValue (), |
|
74 MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces), |
|
75 MakeObjectVectorChecker<Ipv4Interface> ()) |
|
76 ; |
|
77 return tid; |
|
78 } |
|
79 |
|
80 Ipv4L3Protocol::Ipv4L3Protocol() |
|
81 : m_nInterfaces (0), |
|
82 m_identification (0) |
|
83 { |
|
84 NS_LOG_FUNCTION_NOARGS (); |
|
85 m_staticRouting = CreateObject<Ipv4StaticRouting> (); |
|
86 AddRoutingProtocol (m_staticRouting, 0); |
|
87 } |
|
88 |
|
89 Ipv4L3Protocol::~Ipv4L3Protocol () |
|
90 { |
|
91 NS_LOG_FUNCTION (this); |
|
92 } |
|
93 |
|
94 void |
|
95 Ipv4L3Protocol::SetNode (Ptr<Node> node) |
|
96 { |
|
97 m_node = node; |
|
98 SetupLoopback (); |
|
99 } |
|
100 |
|
101 void |
|
102 Ipv4L3Protocol::DoDispose (void) |
|
103 { |
|
104 NS_LOG_FUNCTION (this); |
|
105 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i) |
|
106 { |
|
107 Ptr<Ipv4Interface> interface = *i; |
|
108 interface->Dispose (); |
|
109 } |
|
110 m_interfaces.clear (); |
|
111 m_node = 0; |
|
112 m_staticRouting->Dispose (); |
|
113 m_staticRouting = 0; |
|
114 Object::DoDispose (); |
|
115 } |
|
116 |
|
117 void |
|
118 Ipv4L3Protocol::SetupLoopback (void) |
|
119 { |
|
120 NS_LOG_FUNCTION_NOARGS (); |
|
121 |
|
122 Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> (); |
|
123 interface->SetNode (m_node); |
|
124 interface->SetAddress (Ipv4Address::GetLoopback ()); |
|
125 interface->SetNetworkMask (Ipv4Mask::GetLoopback ()); |
|
126 uint32_t index = AddIpv4Interface (interface); |
|
127 AddHostRouteTo (Ipv4Address::GetLoopback (), index); |
|
128 interface->SetUp (); |
|
129 } |
|
130 |
|
131 void |
|
132 Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl) |
|
133 { |
|
134 NS_LOG_FUNCTION_NOARGS (); |
|
135 m_defaultTtl = ttl; |
|
136 } |
|
137 |
|
138 |
|
139 void |
|
140 Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, |
|
141 Ipv4Address nextHop, |
|
142 uint32_t interface) |
|
143 { |
|
144 NS_LOG_FUNCTION (this << dest << nextHop << interface); |
|
145 m_staticRouting->AddHostRouteTo (dest, nextHop, interface); |
|
146 } |
|
147 |
|
148 void |
|
149 Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, |
|
150 uint32_t interface) |
|
151 { |
|
152 NS_LOG_FUNCTION (this << dest << interface); |
|
153 m_staticRouting->AddHostRouteTo (dest, interface); |
|
154 } |
|
155 |
|
156 void |
|
157 Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, |
|
158 Ipv4Mask networkMask, |
|
159 Ipv4Address nextHop, |
|
160 uint32_t interface) |
|
161 { |
|
162 NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface); |
|
163 m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface); |
|
164 } |
|
165 |
|
166 void |
|
167 Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, |
|
168 Ipv4Mask networkMask, |
|
169 uint32_t interface) |
|
170 { |
|
171 NS_LOG_FUNCTION (this << network << networkMask << interface); |
|
172 m_staticRouting->AddNetworkRouteTo (network, networkMask, interface); |
|
173 } |
|
174 |
|
175 void |
|
176 Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, |
|
177 uint32_t interface) |
|
178 { |
|
179 NS_LOG_FUNCTION (this << nextHop << interface); |
|
180 m_staticRouting->SetDefaultRoute (nextHop, interface); |
|
181 } |
|
182 |
|
183 void |
|
184 Ipv4L3Protocol::Lookup ( |
|
185 Ipv4Header const &ipHeader, |
|
186 Ptr<Packet> packet, |
|
187 Ipv4RoutingProtocol::RouteReplyCallback routeReply) |
|
188 { |
|
189 NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply); |
|
190 |
|
191 Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply); |
|
192 } |
|
193 |
|
194 void |
|
195 Ipv4L3Protocol::Lookup ( |
|
196 uint32_t ifIndex, |
|
197 Ipv4Header const &ipHeader, |
|
198 Ptr<Packet> packet, |
|
199 Ipv4RoutingProtocol::RouteReplyCallback routeReply) |
|
200 { |
|
201 NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply); |
|
202 |
|
203 for (Ipv4RoutingProtocolList::const_iterator rprotoIter = |
|
204 m_routingProtocols.begin (); |
|
205 rprotoIter != m_routingProtocols.end (); |
|
206 rprotoIter++) |
|
207 { |
|
208 NS_LOG_LOGIC ("Requesting route"); |
|
209 if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, |
|
210 routeReply)) |
|
211 return; |
|
212 } |
|
213 |
|
214 if (ipHeader.GetDestination ().IsMulticast () && |
|
215 ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY) |
|
216 { |
|
217 NS_LOG_LOGIC ("Multicast destination with local source"); |
|
218 // |
|
219 // We have a multicast packet originating from the current node and were not |
|
220 // able to send it using the usual RequestRoute process. Since the usual |
|
221 // process includes trying to use a default multicast route, this means that |
|
222 // there was no specific route out of the node found, and there was no default |
|
223 // multicast route set. |
|
224 // |
|
225 // The fallback position is to look for a default unicast route and use that |
|
226 // to get the packet off the node if we have one. |
|
227 // |
|
228 Ipv4Route *route = m_staticRouting->GetDefaultRoute (); |
|
229 |
|
230 if (route) |
|
231 { |
|
232 NS_LOG_LOGIC ("Local source. Using unicast default route for " |
|
233 "multicast packet"); |
|
234 |
|
235 routeReply (true, *route, packet, ipHeader); |
|
236 return; |
|
237 } |
|
238 } |
|
239 // |
|
240 // No route found |
|
241 // |
|
242 routeReply (false, Ipv4Route (), packet, ipHeader); |
|
243 } |
|
244 |
|
245 void |
|
246 Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol, |
|
247 int priority) |
|
248 { |
|
249 NS_LOG_FUNCTION (this << &routingProtocol << priority); |
|
250 m_routingProtocols.push_back |
|
251 (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol)); |
|
252 m_routingProtocols.sort (); |
|
253 } |
|
254 |
|
255 uint32_t |
|
256 Ipv4L3Protocol::GetNRoutes (void) |
|
257 { |
|
258 NS_LOG_FUNCTION_NOARGS (); |
|
259 return m_staticRouting->GetNRoutes (); |
|
260 } |
|
261 |
|
262 Ipv4Route * |
|
263 Ipv4L3Protocol::GetRoute (uint32_t index) |
|
264 { |
|
265 NS_LOG_FUNCTION_NOARGS (); |
|
266 return m_staticRouting->GetRoute (index); |
|
267 } |
|
268 |
|
269 void |
|
270 Ipv4L3Protocol::RemoveRoute (uint32_t index) |
|
271 { |
|
272 NS_LOG_FUNCTION (this << index); |
|
273 m_staticRouting->RemoveRoute (index); |
|
274 } |
|
275 |
|
276 void |
|
277 Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin, |
|
278 Ipv4Address group, |
|
279 uint32_t inputInterface, |
|
280 std::vector<uint32_t> outputInterfaces) |
|
281 { |
|
282 NS_LOG_FUNCTION (this << origin << group << inputInterface << &outputInterfaces); |
|
283 |
|
284 m_staticRouting->AddMulticastRoute (origin, group, inputInterface, |
|
285 outputInterfaces); |
|
286 } |
|
287 |
|
288 void |
|
289 Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface) |
|
290 { |
|
291 NS_LOG_FUNCTION (this << outputInterface); |
|
292 |
|
293 m_staticRouting->SetDefaultMulticastRoute (outputInterface); |
|
294 } |
|
295 |
|
296 uint32_t |
|
297 Ipv4L3Protocol::GetNMulticastRoutes (void) const |
|
298 { |
|
299 NS_LOG_FUNCTION_NOARGS (); |
|
300 return m_staticRouting->GetNMulticastRoutes (); |
|
301 } |
|
302 |
|
303 Ipv4MulticastRoute * |
|
304 Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const |
|
305 { |
|
306 NS_LOG_FUNCTION (this << index); |
|
307 return m_staticRouting->GetMulticastRoute (index); |
|
308 } |
|
309 |
|
310 void |
|
311 Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin, |
|
312 Ipv4Address group, |
|
313 uint32_t inputInterface) |
|
314 { |
|
315 NS_LOG_FUNCTION (this << origin << group << inputInterface); |
|
316 m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface); |
|
317 } |
|
318 |
|
319 void |
|
320 Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index) |
|
321 { |
|
322 NS_LOG_FUNCTION (this << index); |
|
323 m_staticRouting->RemoveMulticastRoute (index); |
|
324 } |
|
325 |
|
326 uint32_t |
|
327 Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device) |
|
328 { |
|
329 NS_LOG_FUNCTION (this << &device); |
|
330 |
|
331 Ptr<Node> node = GetObject<Node> (); |
|
332 node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), |
|
333 Ipv4L3Protocol::PROT_NUMBER, device); |
|
334 node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())), |
|
335 ArpL3Protocol::PROT_NUMBER, device); |
|
336 |
|
337 Ptr<ArpIpv4Interface> interface = CreateObject<ArpIpv4Interface> (); |
|
338 interface->SetNode (m_node); |
|
339 interface->SetDevice (device); |
|
340 return AddIpv4Interface (interface); |
|
341 } |
|
342 |
|
343 uint32_t |
|
344 Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface) |
|
345 { |
|
346 NS_LOG_FUNCTION (this << interface); |
|
347 uint32_t index = m_nInterfaces; |
|
348 m_interfaces.push_back (interface); |
|
349 m_nInterfaces++; |
|
350 return index; |
|
351 } |
|
352 |
|
353 Ptr<Ipv4Interface> |
|
354 Ipv4L3Protocol::GetInterface (uint32_t index) const |
|
355 { |
|
356 NS_LOG_FUNCTION (this << index); |
|
357 uint32_t tmp = 0; |
|
358 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) |
|
359 { |
|
360 if (index == tmp) |
|
361 { |
|
362 return *i; |
|
363 } |
|
364 tmp++; |
|
365 } |
|
366 return 0; |
|
367 } |
|
368 |
|
369 uint32_t |
|
370 Ipv4L3Protocol::GetNInterfaces (void) const |
|
371 { |
|
372 NS_LOG_FUNCTION_NOARGS (); |
|
373 return m_nInterfaces; |
|
374 } |
|
375 |
|
376 uint32_t |
|
377 Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const |
|
378 { |
|
379 NS_LOG_FUNCTION (this << addr); |
|
380 |
|
381 uint32_t ifIndex = 0; |
|
382 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); |
|
383 i != m_interfaces.end (); |
|
384 i++, ifIndex++) |
|
385 { |
|
386 if ((*i)->GetAddress () == addr) |
|
387 { |
|
388 return ifIndex; |
|
389 } |
|
390 } |
|
391 |
|
392 NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): " |
|
393 "Interface not found for IP address " << addr); |
|
394 return 0; |
|
395 } |
|
396 |
|
397 uint32_t |
|
398 Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const |
|
399 { |
|
400 NS_LOG_FUNCTION (this << addr << mask); |
|
401 |
|
402 uint32_t ifIndex = 0; |
|
403 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); |
|
404 i != m_interfaces.end (); |
|
405 i++, ifIndex++) |
|
406 { |
|
407 if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask)) |
|
408 { |
|
409 return ifIndex; |
|
410 } |
|
411 } |
|
412 |
|
413 NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): " |
|
414 "Interface not found for masked IP address"); |
|
415 return 0; |
|
416 } |
|
417 |
|
418 int32_t |
|
419 Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr<NetDevice> device) const |
|
420 { |
|
421 NS_LOG_FUNCTION (this << device); |
|
422 |
|
423 uint32_t ifIndex = 0; |
|
424 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); |
|
425 i != m_interfaces.end (); |
|
426 i++, ifIndex++) |
|
427 { |
|
428 if ((*i)->GetDevice () == device) |
|
429 { |
|
430 return ifIndex; |
|
431 } |
|
432 } |
|
433 |
|
434 return -1; |
|
435 } |
|
436 |
|
437 Ptr<Ipv4Interface> |
|
438 Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device) |
|
439 { |
|
440 NS_LOG_FUNCTION (this << &device); |
|
441 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) |
|
442 { |
|
443 if ((*i)->GetDevice () == device) |
|
444 { |
|
445 return *i; |
|
446 } |
|
447 } |
|
448 return 0; |
|
449 } |
|
450 |
|
451 void |
|
452 Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from) |
|
453 { |
|
454 NS_LOG_FUNCTION (this << &device << packet << protocol << from); |
|
455 |
|
456 NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ()); |
|
457 |
|
458 uint32_t index = 0; |
|
459 Ptr<Ipv4Interface> ipv4Interface; |
|
460 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); |
|
461 i != m_interfaces.end (); |
|
462 i++) |
|
463 { |
|
464 ipv4Interface = *i; |
|
465 if (ipv4Interface->GetDevice () == device) |
|
466 { |
|
467 m_rxTrace (packet, index); |
|
468 break; |
|
469 } |
|
470 index++; |
|
471 } |
|
472 Ipv4Header ipHeader; |
|
473 if (m_calcChecksum) |
|
474 { |
|
475 ipHeader.EnableChecksum (); |
|
476 } |
|
477 packet->RemoveHeader (ipHeader); |
|
478 |
|
479 if (!ipHeader.IsChecksumOk ()) |
|
480 { |
|
481 m_dropTrace (packet); |
|
482 return; |
|
483 } |
|
484 |
|
485 if (Forwarding (index, packet, ipHeader, device)) |
|
486 { |
|
487 return; |
|
488 } |
|
489 |
|
490 ForwardUp (packet, ipHeader, ipv4Interface); |
|
491 } |
|
492 |
|
493 |
|
494 void |
|
495 Ipv4L3Protocol::Send (Ptr<Packet> packet, |
|
496 Ipv4Address source, |
|
497 Ipv4Address destination, |
|
498 uint8_t protocol) |
|
499 { |
|
500 NS_LOG_FUNCTION (this << packet << source << destination << protocol); |
|
501 |
|
502 Ipv4Header ipHeader; |
|
503 |
|
504 if (m_calcChecksum) |
|
505 { |
|
506 ipHeader.EnableChecksum (); |
|
507 } |
|
508 |
|
509 ipHeader.SetSource (source); |
|
510 ipHeader.SetDestination (destination); |
|
511 ipHeader.SetProtocol (protocol); |
|
512 ipHeader.SetPayloadSize (packet->GetSize ()); |
|
513 ipHeader.SetTtl (m_defaultTtl); |
|
514 ipHeader.SetMayFragment (); |
|
515 ipHeader.SetIdentification (m_identification); |
|
516 |
|
517 m_identification ++; |
|
518 |
|
519 // Set TTL to 1 if it is a broadcast packet of any type. Otherwise, |
|
520 // possibly override the default TTL if the packet is tagged |
|
521 SocketIpTtlTag tag; |
|
522 bool found = packet->FindFirstMatchingTag (tag); |
|
523 |
|
524 if (destination.IsBroadcast ()) |
|
525 { |
|
526 ipHeader.SetTtl (1); |
|
527 } |
|
528 else if (found) |
|
529 { |
|
530 ipHeader.SetTtl (tag.GetTtl ()); |
|
531 // XXX remove tag here? |
|
532 } |
|
533 else |
|
534 { |
|
535 uint32_t ifaceIndex = 0; |
|
536 for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); |
|
537 ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) |
|
538 { |
|
539 Ptr<Ipv4Interface> outInterface = *ifaceIter; |
|
540 if (destination.IsSubnetDirectedBroadcast ( |
|
541 outInterface->GetNetworkMask ())) |
|
542 { |
|
543 ipHeader.SetTtl (1); |
|
544 } |
|
545 } |
|
546 } |
|
547 if (destination.IsBroadcast ()) |
|
548 { |
|
549 uint32_t ifaceIndex = 0; |
|
550 for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); |
|
551 ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) |
|
552 { |
|
553 Ptr<Ipv4Interface> outInterface = *ifaceIter; |
|
554 Ptr<Packet> packetCopy = packet->Copy (); |
|
555 |
|
556 NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ()); |
|
557 packetCopy->AddHeader (ipHeader); |
|
558 m_txTrace (packetCopy, ifaceIndex); |
|
559 outInterface->Send (packetCopy, destination); |
|
560 } |
|
561 } |
|
562 else |
|
563 { |
|
564 // XXX Note here that in most ipv4 stacks in the world, |
|
565 // the route calculation for an outgoing packet is not |
|
566 // done in the ip layer. It is done within the application |
|
567 // socket when the first packet is sent to avoid this |
|
568 // costly lookup on a per-packet basis. |
|
569 // That would require us to get the route from the packet, |
|
570 // most likely with a packet tag. The higher layers do not |
|
571 // do this yet for us. |
|
572 Lookup (ipHeader, packet, |
|
573 MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); |
|
574 } |
|
575 } |
|
576 |
|
577 void |
|
578 Ipv4L3Protocol::SendRealOut (bool found, |
|
579 Ipv4Route const &route, |
|
580 Ptr<Packet> packet, |
|
581 Ipv4Header const &ipHeader) |
|
582 { |
|
583 NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader); |
|
584 |
|
585 packet->AddHeader (ipHeader); |
|
586 if (!found) |
|
587 { |
|
588 NS_LOG_WARN ("No route to host. Drop."); |
|
589 m_dropTrace (packet); |
|
590 return; |
|
591 } |
|
592 |
|
593 NS_LOG_LOGIC ("Send via interface " << route.GetInterface ()); |
|
594 |
|
595 Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ()); |
|
596 NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ()); |
|
597 m_txTrace (packet, route.GetInterface ()); |
|
598 if (route.IsGateway ()) |
|
599 { |
|
600 NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ()); |
|
601 outInterface->Send (packet, route.GetGateway ()); |
|
602 } |
|
603 else |
|
604 { |
|
605 NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); |
|
606 outInterface->Send (packet, ipHeader.GetDestination ()); |
|
607 } |
|
608 } |
|
609 |
|
610 bool |
|
611 Ipv4L3Protocol::Forwarding ( |
|
612 uint32_t ifIndex, |
|
613 Ptr<Packet> packet, |
|
614 Ipv4Header &ipHeader, |
|
615 Ptr<NetDevice> device) |
|
616 { |
|
617 NS_LOG_FUNCTION (ifIndex << packet << &ipHeader<< device); |
|
618 NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ()); |
|
619 |
|
620 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); |
|
621 i != m_interfaces.end (); i++) |
|
622 { |
|
623 if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ())) |
|
624 { |
|
625 NS_LOG_LOGIC ("For me (destination match)"); |
|
626 return false; |
|
627 } |
|
628 } |
|
629 |
|
630 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); |
|
631 i != m_interfaces.end (); i++) |
|
632 { |
|
633 Ptr<Ipv4Interface> interface = *i; |
|
634 if (interface->GetDevice () == device) |
|
635 { |
|
636 if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ())) |
|
637 { |
|
638 NS_LOG_LOGIC ("For me (interface broadcast address)"); |
|
639 return false; |
|
640 } |
|
641 break; |
|
642 } |
|
643 } |
|
644 |
|
645 if (ipHeader.GetDestination ().IsBroadcast ()) |
|
646 { |
|
647 NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)"); |
|
648 return false; |
|
649 } |
|
650 |
|
651 if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ())) |
|
652 { |
|
653 NS_LOG_LOGIC ("For me (Ipv4Addr any address)"); |
|
654 return false; |
|
655 } |
|
656 |
|
657 if (ipHeader.GetTtl () == 1) |
|
658 { |
|
659 // Should send ttl expired here |
|
660 // XXX |
|
661 NS_LOG_LOGIC ("Not for me (TTL expired). Drop"); |
|
662 m_dropTrace (packet); |
|
663 return true; |
|
664 } |
|
665 ipHeader.SetTtl (ipHeader.GetTtl () - 1); |
|
666 |
|
667 // |
|
668 // If this is a to a multicast address and this node is a member of the |
|
669 // indicated group we need to return false so the multicast is forwarded up. |
|
670 // |
|
671 for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin (); |
|
672 i != m_multicastGroups.end (); i++) |
|
673 { |
|
674 if ((*i).first.IsEqual (ipHeader.GetSource ()) && |
|
675 (*i).second.IsEqual (ipHeader.GetDestination ())) |
|
676 { |
|
677 NS_LOG_LOGIC ("For me (Joined multicast group)"); |
|
678 // We forward with a packet copy, since forwarding may change |
|
679 // the packet, affecting our local delivery |
|
680 NS_LOG_LOGIC ("Forwarding (multicast)."); |
|
681 Lookup (ifIndex, ipHeader, packet->Copy (), |
|
682 MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); |
|
683 return false; |
|
684 } |
|
685 } |
|
686 NS_LOG_LOGIC ("Not for me, forwarding."); |
|
687 Lookup (ifIndex, ipHeader, packet, |
|
688 MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); |
|
689 |
|
690 return true; |
|
691 } |
|
692 |
|
693 void |
|
694 Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip, |
|
695 Ptr<Ipv4Interface> incomingInterface) |
|
696 { |
|
697 NS_LOG_FUNCTION (this << p << &ip); |
|
698 |
|
699 Ptr<Ipv4L4Demux> demux = m_node->GetObject<Ipv4L4Demux> (); |
|
700 Ptr<Ipv4L4Protocol> protocol = demux->GetProtocol (ip.GetProtocol ()); |
|
701 protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface); |
|
702 } |
|
703 |
|
704 void |
|
705 Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) |
|
706 { |
|
707 NS_LOG_FUNCTION (this << origin << group); |
|
708 m_multicastGroups.push_back( |
|
709 std::pair<Ipv4Address, Ipv4Address> (origin, group)); |
|
710 } |
|
711 |
|
712 void |
|
713 Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) |
|
714 { |
|
715 NS_LOG_FUNCTION (this << origin << group); |
|
716 |
|
717 for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin (); |
|
718 i != m_multicastGroups.end (); |
|
719 i++) |
|
720 { |
|
721 if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group)) |
|
722 { |
|
723 m_multicastGroups.erase (i); |
|
724 return; |
|
725 } |
|
726 } |
|
727 } |
|
728 |
|
729 void |
|
730 Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address) |
|
731 { |
|
732 NS_LOG_FUNCTION (this << i << address); |
|
733 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
734 interface->SetAddress (address); |
|
735 } |
|
736 |
|
737 void |
|
738 Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask) |
|
739 { |
|
740 NS_LOG_FUNCTION (this << i << mask); |
|
741 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
742 interface->SetNetworkMask (mask); |
|
743 } |
|
744 |
|
745 Ipv4Mask |
|
746 Ipv4L3Protocol::GetNetworkMask (uint32_t i) const |
|
747 { |
|
748 NS_LOG_FUNCTION (this << i); |
|
749 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
750 return interface->GetNetworkMask (); |
|
751 } |
|
752 |
|
753 Ipv4Address |
|
754 Ipv4L3Protocol::GetAddress (uint32_t i) const |
|
755 { |
|
756 NS_LOG_FUNCTION (this << i); |
|
757 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
758 return interface->GetAddress (); |
|
759 } |
|
760 |
|
761 void |
|
762 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric) |
|
763 { |
|
764 NS_LOG_FUNCTION (i << metric); |
|
765 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
766 interface->SetMetric (metric); |
|
767 } |
|
768 |
|
769 uint16_t |
|
770 Ipv4L3Protocol::GetMetric (uint32_t i) const |
|
771 { |
|
772 NS_LOG_FUNCTION (i); |
|
773 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
774 return interface->GetMetric (); |
|
775 } |
|
776 |
|
777 bool |
|
778 Ipv4L3Protocol::GetIfIndexForDestination ( |
|
779 Ipv4Address destination, uint32_t& ifIndex) const |
|
780 { |
|
781 NS_LOG_FUNCTION (this << destination << &ifIndex); |
|
782 // |
|
783 // The first thing we do in trying to determine a source address is to |
|
784 // consult the routing protocols. These will also check for a default route |
|
785 // if one has been set. |
|
786 // |
|
787 for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin (); |
|
788 i != m_routingProtocols.end (); |
|
789 i++) |
|
790 { |
|
791 NS_LOG_LOGIC ("Requesting Source Address"); |
|
792 uint32_t ifIndexTmp; |
|
793 |
|
794 if ((*i).second->RequestIfIndex (destination, ifIndexTmp)) |
|
795 { |
|
796 NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp); |
|
797 ifIndex = ifIndexTmp; |
|
798 return true; |
|
799 } |
|
800 } |
|
801 // |
|
802 // If there's no routing table entry telling us what *single* interface will |
|
803 // be used to send a packet to this destination, we'll have to just pick one. |
|
804 // If there's only one interface on this node, a good answer isn't very hard |
|
805 // to come up with. Before jumping to any conclusions, remember that the |
|
806 // zeroth interface is the loopback interface, so what we actually want is |
|
807 // a situation where there are exactly two interfaces on the node, in which |
|
808 // case interface one is the "single" interface connected to the outside world. |
|
809 // |
|
810 if (GetNInterfaces () == 2) |
|
811 { |
|
812 NS_LOG_LOGIC ("One Interface. Using interface 1."); |
|
813 ifIndex = 1; |
|
814 return true; |
|
815 } |
|
816 // |
|
817 // If we fall through to here, we have a node with multiple interfaces and |
|
818 // no routes to guide us in determining what interface to choose. Either |
|
819 // no default route was found (for unicast or multicast), or in the case of a |
|
820 // multicast, the default route contained multiple outbound interfaces. |
|
821 // |
|
822 // The fallback position is to just get the unicast default route and use |
|
823 // the outgoing interface specified there. We don't want to leave the source |
|
824 // address unset, so we just assert here. |
|
825 // |
|
826 // N.B. that in the case of a multicast with a route containing multiple |
|
827 // outgoing interfaces, the source address of packets from that node will be |
|
828 // set to the IP address of the interface set in the default unicast route. |
|
829 // Also, in the case of a broadcast, the same will be true. |
|
830 // |
|
831 NS_LOG_LOGIC ("Using default unicast route"); |
|
832 Ipv4Route *route = m_staticRouting->GetDefaultRoute (); |
|
833 |
|
834 if (route == NULL) |
|
835 { |
|
836 NS_LOG_LOGIC ("Ipv4L3Protocol::GetIfIndexForDestination (): " |
|
837 "Unable to determine outbound interface. No default route set"); |
|
838 return false; |
|
839 } |
|
840 |
|
841 ifIndex = route->GetInterface (); |
|
842 |
|
843 NS_LOG_LOGIC ("Default route specifies interface " << ifIndex); |
|
844 return true; |
|
845 } |
|
846 |
|
847 uint16_t |
|
848 Ipv4L3Protocol::GetMtu (uint32_t i) const |
|
849 { |
|
850 NS_LOG_FUNCTION (this << i); |
|
851 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
852 return interface->GetMtu (); |
|
853 } |
|
854 |
|
855 bool |
|
856 Ipv4L3Protocol::IsUp (uint32_t i) const |
|
857 { |
|
858 NS_LOG_FUNCTION (this << i); |
|
859 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
860 return interface->IsUp (); |
|
861 } |
|
862 |
|
863 void |
|
864 Ipv4L3Protocol::SetUp (uint32_t i) |
|
865 { |
|
866 NS_LOG_FUNCTION (this << i); |
|
867 Ptr<Ipv4Interface> interface = GetInterface (i); |
|
868 interface->SetUp (); |
|
869 |
|
870 // If interface address and network mask have been set, add a route |
|
871 // to the network of the interface (like e.g. ifconfig does on a |
|
872 // Linux box) |
|
873 if ((interface->GetAddress ()) != (Ipv4Address ()) |
|
874 && (interface->GetNetworkMask ()) != (Ipv4Mask ())) |
|
875 { |
|
876 AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()), |
|
877 interface->GetNetworkMask (), i); |
|
878 } |
|
879 } |
|
880 |
|
881 void |
|
882 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) |
|
883 { |
|
884 NS_LOG_FUNCTION (this << ifaceIndex); |
|
885 Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex); |
|
886 interface->SetDown (); |
|
887 |
|
888 // Remove all routes that are going through this interface |
|
889 bool modified = true; |
|
890 while (modified) |
|
891 { |
|
892 modified = false; |
|
893 for (uint32_t i = 0; i < GetNRoutes (); i++) |
|
894 { |
|
895 Ipv4Route *route = GetRoute (i); |
|
896 if (route->GetInterface () == ifaceIndex) |
|
897 { |
|
898 RemoveRoute (i); |
|
899 modified = true; |
|
900 break; |
|
901 } |
|
902 } |
|
903 } |
|
904 } |
|
905 |
|
906 }//namespace ns3 |