A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv6-end-point-demux.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007-2009 Strasbourg University
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
18 */
19
21
22#include "ipv6-end-point.h"
23
24#include "ns3/log.h"
25
26namespace ns3
27{
28
29NS_LOG_COMPONENT_DEFINE("Ipv6EndPointDemux");
30
32 : m_ephemeral(49152),
33 m_portFirst(49152),
34 m_portLast(65535)
35{
36 NS_LOG_FUNCTION(this);
37}
38
40{
41 NS_LOG_FUNCTION(this);
42 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
43 {
44 Ipv6EndPoint* endPoint = *i;
45 delete endPoint;
46 }
47 m_endPoints.clear();
48}
49
50bool
52{
53 NS_LOG_FUNCTION(this << port);
54 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
55 {
56 if ((*i)->GetLocalPort() == port)
57 {
58 return true;
59 }
60 }
61 return false;
62}
63
64bool
66{
67 NS_LOG_FUNCTION(this << addr << port);
68 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
69 {
70 if ((*i)->GetLocalPort() == port && (*i)->GetLocalAddress() == addr &&
71 (*i)->GetBoundNetDevice() == boundNetDevice)
72 {
73 return true;
74 }
75 }
76 return false;
77}
78
81{
82 NS_LOG_FUNCTION(this);
83 uint16_t port = AllocateEphemeralPort();
84 if (port == 0)
85 {
86 NS_LOG_WARN("Ephemeral port allocation failed.");
87 return nullptr;
88 }
89 auto endPoint = new Ipv6EndPoint(Ipv6Address::GetAny(), port);
90 m_endPoints.push_back(endPoint);
91 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
92 return endPoint;
93}
94
97{
98 NS_LOG_FUNCTION(this << address);
99 uint16_t port = AllocateEphemeralPort();
100 if (port == 0)
101 {
102 NS_LOG_WARN("Ephemeral port allocation failed.");
103 return nullptr;
104 }
105 auto endPoint = new Ipv6EndPoint(address, port);
106 m_endPoints.push_back(endPoint);
107 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
108 return endPoint;
109}
110
113{
114 NS_LOG_FUNCTION(this << boundNetDevice << port);
115
116 return Allocate(boundNetDevice, Ipv6Address::GetAny(), port);
117}
118
121{
122 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
123 if (LookupLocal(boundNetDevice, address, port) || LookupLocal(nullptr, address, port))
124 {
125 NS_LOG_WARN("Duplicated endpoint.");
126 return nullptr;
127 }
128 auto endPoint = new Ipv6EndPoint(address, port);
129 m_endPoints.push_back(endPoint);
130 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
131 return endPoint;
132}
133
136 Ipv6Address localAddress,
137 uint16_t localPort,
138 Ipv6Address peerAddress,
139 uint16_t peerPort)
140{
141 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
142 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
143 {
144 if ((*i)->GetLocalPort() == localPort && (*i)->GetLocalAddress() == localAddress &&
145 (*i)->GetPeerPort() == peerPort && (*i)->GetPeerAddress() == peerAddress &&
146 ((*i)->GetBoundNetDevice() == boundNetDevice || !(*i)->GetBoundNetDevice()))
147 {
148 NS_LOG_WARN("Duplicated endpoint.");
149 return nullptr;
150 }
151 }
152 auto endPoint = new Ipv6EndPoint(localAddress, localPort);
153 endPoint->SetPeer(peerAddress, peerPort);
154 m_endPoints.push_back(endPoint);
155
156 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
157
158 return endPoint;
159}
160
161void
163{
164 NS_LOG_FUNCTION(this);
165 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
166 {
167 if (*i == endPoint)
168 {
169 delete endPoint;
170 m_endPoints.erase(i);
171 break;
172 }
173 }
174}
175
176/*
177 * If we have an exact match, we return it.
178 * Otherwise, if we find a generic match, we return it.
179 * Otherwise, we return 0.
180 */
183 uint16_t dport,
184 Ipv6Address saddr,
185 uint16_t sport,
186 Ptr<Ipv6Interface> incomingInterface)
187{
188 NS_LOG_FUNCTION(this << daddr << dport << saddr << sport << incomingInterface);
189
190 EndPoints retval1; /* Matches exact on local port, wildcards on others */
191 EndPoints retval2; /* Matches exact on local port/adder, wildcards on others */
192 EndPoints retval3; /* Matches all but local address */
193 EndPoints retval4; /* Exact match on all 4 */
194
195 NS_LOG_DEBUG("Looking up endpoint for destination address " << daddr);
196 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
197 {
198 Ipv6EndPoint* endP = *i;
199
200 NS_LOG_DEBUG("Looking at endpoint dport="
201 << endP->GetLocalPort() << " daddr=" << endP->GetLocalAddress()
202 << " sport=" << endP->GetPeerPort() << " saddr=" << endP->GetPeerAddress());
203
204 if (!endP->IsRxEnabled())
205 {
206 NS_LOG_LOGIC("Skipping endpoint " << &endP
207 << " because endpoint can not receive packets");
208 continue;
209 }
210
211 if (endP->GetLocalPort() != dport)
212 {
213 NS_LOG_LOGIC("Skipping endpoint " << &endP << " because endpoint dport "
214 << endP->GetLocalPort()
215 << " does not match packet dport " << dport);
216 continue;
217 }
218
219 if (endP->GetBoundNetDevice())
220 {
221 if (!incomingInterface)
222 {
223 continue;
224 }
225 if (endP->GetBoundNetDevice() != incomingInterface->GetDevice())
226 {
227 NS_LOG_LOGIC("Skipping endpoint "
228 << &endP << " because endpoint is bound to specific device and"
229 << endP->GetBoundNetDevice() << " does not match packet device "
230 << incomingInterface->GetDevice());
231 continue;
232 }
233 }
234
235 /* Ipv6Address incomingInterfaceAddr = incomingInterface->GetAddress (); */
236 NS_LOG_DEBUG("dest addr " << daddr);
237
238 bool localAddressMatchesWildCard = endP->GetLocalAddress() == Ipv6Address::GetAny();
239 bool localAddressMatchesExact = endP->GetLocalAddress() == daddr;
240 bool localAddressMatchesAllRouters =
242
243 /* if no match here, keep looking */
244 if (!(localAddressMatchesExact || localAddressMatchesWildCard))
245 {
246 continue;
247 }
248 bool remotePeerMatchesExact = endP->GetPeerPort() == sport;
249 bool remotePeerMatchesWildCard = endP->GetPeerPort() == 0;
250 bool remoteAddressMatchesExact = endP->GetPeerAddress() == saddr;
251 bool remoteAddressMatchesWildCard = endP->GetPeerAddress() == Ipv6Address::GetAny();
252
253 /* If remote does not match either with exact or wildcard,i
254 skip this one */
255 if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
256 {
257 continue;
258 }
259 if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
260 {
261 continue;
262 }
263
264 /* Now figure out which return list to add this one to */
265 if (localAddressMatchesWildCard && remotePeerMatchesWildCard &&
266 remoteAddressMatchesWildCard)
267 { /* Only local port matches exactly */
268 retval1.push_back(endP);
269 }
270 if ((localAddressMatchesExact || (localAddressMatchesAllRouters)) &&
271 remotePeerMatchesWildCard && remoteAddressMatchesWildCard)
272 { /* Only local port and local address matches exactly */
273 retval2.push_back(endP);
274 }
275 if (localAddressMatchesWildCard && remotePeerMatchesExact && remoteAddressMatchesExact)
276 { /* All but local address */
277 retval3.push_back(endP);
278 }
279 if (localAddressMatchesExact && remotePeerMatchesExact && remoteAddressMatchesExact)
280 { /* All 4 match */
281 retval4.push_back(endP);
282 }
283 }
284
285 // Here we find the most exact match
286 EndPoints retval;
287 if (!retval4.empty())
288 {
289 retval = retval4;
290 }
291 else if (!retval3.empty())
292 {
293 retval = retval3;
294 }
295 else if (!retval2.empty())
296 {
297 retval = retval2;
298 }
299 else
300 {
301 retval = retval1;
302 }
303
304 NS_ABORT_MSG_IF(retval.size() > 1,
305 "Too many endpoints - perhaps you created too many sockets without binding "
306 "them to different NetDevices.");
307 return retval; // might be empty if no matches
308}
309
311Ipv6EndPointDemux::SimpleLookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
312{
313 uint32_t genericity = 3;
314 Ipv6EndPoint* generic = nullptr;
315
316 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
317 {
318 uint32_t tmp = 0;
319
320 if ((*i)->GetLocalPort() != dport)
321 {
322 continue;
323 }
324
325 if ((*i)->GetLocalAddress() == dst && (*i)->GetPeerPort() == sport &&
326 (*i)->GetPeerAddress() == src)
327 {
328 /* this is an exact match. */
329 return *i;
330 }
331
332 if ((*i)->GetLocalAddress() == Ipv6Address::GetAny())
333 {
334 tmp++;
335 }
336
337 if ((*i)->GetPeerAddress() == Ipv6Address::GetAny())
338 {
339 tmp++;
340 }
341
342 if (tmp < genericity)
343 {
344 generic = (*i);
345 genericity = tmp;
346 }
347 }
348 return generic;
349}
350
351uint16_t
353{
354 NS_LOG_FUNCTION(this);
355 uint16_t port = m_ephemeral;
356 int count = m_portLast - m_portFirst;
357 do
358 {
359 if (count-- < 0)
360 {
361 return 0;
362 }
363 ++port;
364 if (port < m_portFirst || port > m_portLast)
365 {
367 }
368 } while (LookupPortLocal(port));
370 return port;
371}
372
375{
376 return m_endPoints;
377}
378
379} /* namespace ns3 */
Describes an IPv6 address.
Definition: ipv6-address.h:49
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
static Ipv6Address GetAllRoutersMulticast()
Get the "all routers multicast" address.
EndPoints Lookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport, Ptr< Ipv6Interface > incomingInterface)
lookup for a match with all the parameters.
Ipv6EndPoint * Allocate()
Allocate a Ipv6EndPoint.
bool LookupLocal(Ptr< NetDevice > boundNetDevice, Ipv6Address addr, uint16_t port)
Lookup for address and port.
EndPoints m_endPoints
A list of IPv6 end points.
uint16_t m_ephemeral
The ephemeral port.
EndPoints GetEndPoints() const
Get the entire list of end points registered.
Ipv6EndPoint * SimpleLookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
Simple lookup for a four-tuple match.
bool LookupPortLocal(uint16_t port)
Lookup for port local.
uint16_t AllocateEphemeralPort()
Allocate a ephemeral port.
uint16_t m_portFirst
The first ephemeral port.
uint16_t m_portLast
The last ephemeral port.
void DeAllocate(Ipv6EndPoint *endPoint)
Remove a end point.
std::list< Ipv6EndPoint * > EndPoints
Container of the IPv6 endpoints.
A representation of an IPv6 endpoint/connection.
uint16_t GetLocalPort() const
Get the local port.
Ipv6Address GetPeerAddress() const
Get the peer address.
Ipv6Address GetLocalAddress() const
Get the local address.
bool IsRxEnabled() const
Checks if the endpoint can receive packets.
Ptr< NetDevice > GetBoundNetDevice() const
Returns socket's bound netdevice, if any.
uint16_t GetPeerPort() const
Get the peer port.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
uint16_t port
Definition: dsdv-manet.cc:44
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
Every class exported by the ns3 library is enclosed in the ns3 namespace.