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 (EndPointsI 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 (EndPointsI 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 (EndPointsI 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  }
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  Ipv6EndPoint* 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  Ipv6EndPoint* 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 (EndPointsI 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  Ipv6EndPoint* 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 (EndPointsI 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 (EndPointsI 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 (EndPointsI 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:50
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.
std::list< Ipv6EndPoint * >::iterator EndPointsI
Iterator to the container of the IPv6 endpoints.
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.
Ipv6Address GetLocalAddress()
Get the local address.
uint16_t GetLocalPort() const
Get the local port.
void SetPeer(Ipv6Address addr, uint16_t port)
Set the peer information (address and port).
Ptr< NetDevice > GetBoundNetDevice()
Returns socket's bound netdevice, if any.
Ipv6Address GetPeerAddress()
Get the peer address.
bool IsRxEnabled() const
Checks if the endpoint can receive packets.
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:78
uint16_t port
Definition: dsdv-manet.cc:45
#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:40
Every class exported by the ns3 library is enclosed in the ns3 namespace.