|
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2009 University of Washington |
|
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 */ |
|
19 |
|
20 #include "ns3/log.h" |
|
21 #include "ns3/ipv4.h" |
|
22 #include "ns3/ipv4-route.h" |
|
23 #include "ns3/node.h" |
|
24 #include "ns3/ipv4-static-routing.h" |
|
25 #include "ipv4-list-routing-impl.h" |
|
26 |
|
27 NS_LOG_COMPONENT_DEFINE ("Ipv4ListRoutingImpl"); |
|
28 |
|
29 namespace ns3 { |
|
30 |
|
31 NS_OBJECT_ENSURE_REGISTERED (Ipv4ListRoutingImpl); |
|
32 |
|
33 TypeId |
|
34 Ipv4ListRoutingImpl::GetTypeId (void) |
|
35 { |
|
36 static TypeId tid = TypeId ("ns3::Ipv4ListRoutingImpl") |
|
37 .SetParent<Ipv4ListRouting> () |
|
38 ; |
|
39 return tid; |
|
40 } |
|
41 |
|
42 |
|
43 Ipv4ListRoutingImpl::Ipv4ListRoutingImpl () |
|
44 : m_node (0) |
|
45 { |
|
46 NS_LOG_FUNCTION_NOARGS (); |
|
47 } |
|
48 |
|
49 Ipv4ListRoutingImpl::~Ipv4ListRoutingImpl () |
|
50 { |
|
51 NS_LOG_FUNCTION_NOARGS (); |
|
52 } |
|
53 |
|
54 void |
|
55 Ipv4ListRoutingImpl::DoDispose (void) |
|
56 { |
|
57 NS_LOG_FUNCTION_NOARGS (); |
|
58 for (Ipv4RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin (); |
|
59 rprotoIter != m_routingProtocols.end (); rprotoIter++) |
|
60 { |
|
61 // Note: Calling dispose on these protocols causes memory leak |
|
62 // The routing protocols should not maintain a pointer to |
|
63 // this object, so Dispose() shouldn't be necessary. |
|
64 (*rprotoIter).second = 0; |
|
65 } |
|
66 m_routingProtocols.clear (); |
|
67 m_node = 0; |
|
68 } |
|
69 |
|
70 Ptr<Ipv4Route> |
|
71 Ipv4ListRoutingImpl::RouteOutput (const Ipv4Header &header, uint32_t oif, enum Socket::SocketErrno &sockerr) |
|
72 { |
|
73 NS_LOG_FUNCTION (this << header.GetDestination () << " " << header.GetSource () << " " << oif); |
|
74 Ptr<Ipv4Route> route; |
|
75 |
|
76 for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin (); |
|
77 i != m_routingProtocols.end (); |
|
78 i++) |
|
79 { |
|
80 NS_LOG_LOGIC ("Checking protocol " << (*i).second->GetInstanceTypeId () << " with priority " << (*i).first); |
|
81 NS_LOG_LOGIC ("Requesting source address for destination " << header.GetDestination ()); |
|
82 route = (*i).second->RouteOutput (header, oif, sockerr); |
|
83 if (route) |
|
84 { |
|
85 NS_LOG_LOGIC ("Found route " << route); |
|
86 sockerr = Socket::ERROR_NOTERROR; |
|
87 return route; |
|
88 } |
|
89 } |
|
90 NS_LOG_LOGIC ("Done checking " << GetTypeId ()); |
|
91 NS_LOG_LOGIC (""); |
|
92 sockerr = Socket::ERROR_NOROUTETOHOST; |
|
93 return 0; |
|
94 } |
|
95 |
|
96 // Patterned after Linux ip_route_input and ip_route_input_slow |
|
97 bool |
|
98 Ipv4ListRoutingImpl::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev, |
|
99 UnicastForwardCallback ucb, MulticastForwardCallback mcb, |
|
100 LocalDeliverCallback lcb, ErrorCallback ecb) |
|
101 { |
|
102 bool retVal = false; |
|
103 NS_LOG_FUNCTION (p << header << idev); |
|
104 NS_LOG_LOGIC ("RouteInput logic for node: " << m_node->GetId ()); |
|
105 |
|
106 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> (); |
|
107 NS_ASSERT (ipv4); |
|
108 uint32_t iif = ipv4->GetInterfaceForDevice (idev); |
|
109 |
|
110 // Multicast recognition; handle local delivery here |
|
111 // |
|
112 if (header.GetDestination().IsMulticast ()) |
|
113 { |
|
114 #ifdef NOTYET |
|
115 if (ipv4->MulticastCheckGroup (iif, header.GetDestination ())) |
|
116 #endif |
|
117 if (true) |
|
118 { |
|
119 NS_LOG_LOGIC ("Multicast packet for me-- local deliver"); |
|
120 Ptr<Packet> packetCopy = p->Copy(); |
|
121 // Here may want to disable lcb callback in recursive RouteInput |
|
122 // call below |
|
123 lcb (packetCopy, header, iif); |
|
124 // Fall through-- we may also need to forward this |
|
125 retVal = true; |
|
126 } |
|
127 for (Ipv4RoutingProtocolList::const_iterator rprotoIter = |
|
128 m_routingProtocols.begin (); |
|
129 rprotoIter != m_routingProtocols.end (); |
|
130 rprotoIter++) |
|
131 { |
|
132 NS_LOG_LOGIC ("Multicast packet for me-- trying to forward"); |
|
133 if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb)) |
|
134 { |
|
135 retVal = true; |
|
136 } |
|
137 } |
|
138 return retVal; |
|
139 } |
|
140 |
|
141 if (header.GetDestination ().IsBroadcast ()) |
|
142 { |
|
143 NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)"); |
|
144 // TODO: Local Deliver for broadcast |
|
145 // TODO: Forward broadcast |
|
146 } |
|
147 |
|
148 // TODO: Configurable option to enable RFC 1222 Strong End System Model |
|
149 // Right now, we will be permissive and allow a source to send us |
|
150 // a packet to one of our other interface addresses; that is, the |
|
151 // destination unicast address does not match one of the iif addresses, |
|
152 // but we check our other interfaces. This could be an option |
|
153 // (to remove the outer loop immediately below and just check iif). |
|
154 for (uint32_t j = 0; j < ipv4->GetNInterfaces (); j++) |
|
155 { |
|
156 for (uint32_t i = 0; i < ipv4->GetNAddresses (j); i++) |
|
157 { |
|
158 Ipv4InterfaceAddress iaddr = ipv4->GetAddress (j, i); |
|
159 Ipv4Address addr = iaddr.GetLocal (); |
|
160 if (addr.IsEqual (header.GetDestination ())) |
|
161 { |
|
162 if (j == iif) |
|
163 { |
|
164 NS_LOG_LOGIC ("For me (destination " << addr << " match)"); |
|
165 } |
|
166 else |
|
167 { |
|
168 NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestination ()); |
|
169 } |
|
170 lcb (p, header, iif); |
|
171 return true; |
|
172 } |
|
173 if (header.GetDestination ().IsEqual (iaddr.GetBroadcast ())) |
|
174 { |
|
175 NS_LOG_LOGIC ("For me (interface broadcast address)"); |
|
176 lcb (p, header, iif); |
|
177 return true; |
|
178 } |
|
179 NS_LOG_LOGIC ("Address "<< addr << " not a match"); |
|
180 } |
|
181 } |
|
182 // Next, try to find a route |
|
183 for (Ipv4RoutingProtocolList::const_iterator rprotoIter = |
|
184 m_routingProtocols.begin (); |
|
185 rprotoIter != m_routingProtocols.end (); |
|
186 rprotoIter++) |
|
187 { |
|
188 if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb)) |
|
189 { |
|
190 return true; |
|
191 } |
|
192 } |
|
193 // No routing protocol has found a route. |
|
194 return retVal; |
|
195 } |
|
196 |
|
197 void |
|
198 Ipv4ListRoutingImpl::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol, int16_t priority) |
|
199 { |
|
200 NS_LOG_FUNCTION (this << routingProtocol->GetInstanceTypeId () << priority); |
|
201 m_routingProtocols.push_back |
|
202 (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol)); |
|
203 m_routingProtocols.sort (); |
|
204 } |
|
205 |
|
206 uint32_t |
|
207 Ipv4ListRoutingImpl::GetNRoutingProtocols (void) const |
|
208 { |
|
209 NS_LOG_FUNCTION (this); |
|
210 return m_routingProtocols.size (); |
|
211 } |
|
212 |
|
213 Ptr<Ipv4RoutingProtocol> |
|
214 Ipv4ListRoutingImpl::GetRoutingProtocol (uint32_t index, int16_t& priority) const |
|
215 { |
|
216 NS_LOG_FUNCTION (index); |
|
217 if (index > m_routingProtocols.size ()) |
|
218 { |
|
219 NS_FATAL_ERROR ("Ipv4ListRoutingImpl::GetRoutingProtocol(): index " << index << " out of range"); |
|
220 } |
|
221 uint32_t i = 0; |
|
222 for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); |
|
223 rprotoIter != m_routingProtocols.end (); rprotoIter++, i++) |
|
224 { |
|
225 if (i == index) |
|
226 { |
|
227 priority = (*rprotoIter).first; |
|
228 return (*rprotoIter).second; |
|
229 } |
|
230 } |
|
231 return 0; |
|
232 } |
|
233 |
|
234 Ptr<Ipv4StaticRouting> |
|
235 Ipv4ListRoutingImpl::GetStaticRouting (void) const |
|
236 { |
|
237 NS_LOG_FUNCTION (this); |
|
238 Ipv4StaticRouting* srp; |
|
239 for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); |
|
240 rprotoIter != m_routingProtocols.end (); rprotoIter++) |
|
241 { |
|
242 NS_LOG_LOGIC ("Searching for static routing"); |
|
243 srp = dynamic_cast<Ipv4StaticRouting*> (PeekPointer((*rprotoIter).second)); |
|
244 if (srp) |
|
245 { |
|
246 NS_LOG_LOGIC ("Found static routing"); |
|
247 return Ptr<Ipv4StaticRouting> (srp); |
|
248 } |
|
249 } |
|
250 NS_LOG_LOGIC ("Static routing not found"); |
|
251 return 0; |
|
252 |
|
253 } |
|
254 |
|
255 void |
|
256 Ipv4ListRoutingImpl::SetNode (Ptr<Node> node) |
|
257 { |
|
258 NS_LOG_FUNCTION_NOARGS (); |
|
259 m_node = node; |
|
260 } |
|
261 |
|
262 Ptr<Node> |
|
263 Ipv4ListRoutingImpl::GetNode (void) const |
|
264 { |
|
265 NS_LOG_FUNCTION_NOARGS (); |
|
266 return m_node; |
|
267 } |
|
268 |
|
269 |
|
270 }//namespace ns3 |