A Discrete-Event Network Simulator
API
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 
20 #include "ipv6-end-point-demux.h"
21 
22 #include "ipv6-end-point.h"
23 
24 #include "ns3/log.h"
25 
26 namespace ns3
27 {
28 
29 NS_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 
50 bool
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 
64 bool
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 
161 void
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 
311 Ipv6EndPointDemux::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 
351 uint16_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  {
366  port = m_portFirst;
367  }
368  } while (LookupPortLocal(port));
369  m_ephemeral = 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.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
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
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.