A Discrete-Event Network Simulator
API
ipv6-end-point-demux.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007-2009 Strasbourg University
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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19  */
20 
21 #include "ipv6-end-point-demux.h"
22 #include "ipv6-end-point.h"
23 #include "ns3/log.h"
24 
25 namespace ns3 {
26 
27 NS_LOG_COMPONENT_DEFINE ("Ipv6EndPointDemux");
28 
30  : m_ephemeral (49152),
31  m_portFirst (49152),
32  m_portLast (65535)
33 {
35 }
36 
38 {
40  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
41  {
42  Ipv6EndPoint *endPoint = *i;
43  delete endPoint;
44  }
45  m_endPoints.clear ();
46 }
47 
49 {
50  NS_LOG_FUNCTION (this << port);
51  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
52  {
53  if ((*i)->GetLocalPort () == port)
54  {
55  return true;
56  }
57  }
58  return false;
59 }
60 
62 {
63  NS_LOG_FUNCTION (this << addr << port);
64  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
65  {
66  if ((*i)->GetLocalPort () == port
67  && (*i)->GetLocalAddress () == addr)
68  {
69  return true;
70  }
71  }
72  return false;
73 }
74 
76 {
78  uint16_t port = AllocateEphemeralPort ();
79  if (port == 0)
80  {
81  NS_LOG_WARN ("Ephemeral port allocation failed.");
82  return 0;
83  }
84  Ipv6EndPoint *endPoint = new Ipv6EndPoint (Ipv6Address::GetAny (), port);
85  m_endPoints.push_back (endPoint);
86  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
87  return endPoint;
88 }
89 
91 {
92  NS_LOG_FUNCTION (this << address);
93  uint16_t port = AllocateEphemeralPort ();
94  if (port == 0)
95  {
96  NS_LOG_WARN ("Ephemeral port allocation failed.");
97  return 0;
98  }
99  Ipv6EndPoint *endPoint = new Ipv6EndPoint (address, port);
100  m_endPoints.push_back (endPoint);
101  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
102  return endPoint;
103 }
104 
106 {
107  NS_LOG_FUNCTION (this << port);
108 
109  return Allocate (Ipv6Address::GetAny (), port);
110 }
111 
113 {
114  NS_LOG_FUNCTION (this << address << port);
115  if (LookupLocal (address, port))
116  {
117  NS_LOG_WARN ("Duplicate address/port; failing.");
118  return 0;
119  }
120  Ipv6EndPoint *endPoint = new Ipv6EndPoint (address, port);
121  m_endPoints.push_back (endPoint);
122  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
123  return endPoint;
124 }
125 
126 Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address localAddress, uint16_t localPort,
127  Ipv6Address peerAddress, uint16_t peerPort)
128 {
129  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
130  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
131  {
132  if ((*i)->GetLocalPort () == localPort
133  && (*i)->GetLocalAddress () == localAddress
134  && (*i)->GetPeerPort () == peerPort
135  && (*i)->GetPeerAddress () == peerAddress)
136  {
137  NS_LOG_WARN ("No way we can allocate this end-point.");
138  /* no way we can allocate this end-point. */
139  return 0;
140  }
141  }
142  Ipv6EndPoint *endPoint = new Ipv6EndPoint (localAddress, localPort);
143  endPoint->SetPeer (peerAddress, peerPort);
144  m_endPoints.push_back (endPoint);
145 
146  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
147 
148  return endPoint;
149 }
150 
152 {
154  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
155  {
156  if (*i == endPoint)
157  {
158  delete endPoint;
159  m_endPoints.erase (i);
160  break;
161  }
162  }
163 }
164 
165 /*
166  * If we have an exact match, we return it.
167  * Otherwise, if we find a generic match, we return it.
168  * Otherwise, we return 0.
169  */
171  Ipv6Address saddr, uint16_t sport,
172  Ptr<Ipv6Interface> incomingInterface)
173 {
174  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface);
175 
176  EndPoints retval1; /* Matches exact on local port, wildcards on others */
177  EndPoints retval2; /* Matches exact on local port/adder, wildcards on others */
178  EndPoints retval3; /* Matches all but local address */
179  EndPoints retval4; /* Exact match on all 4 */
180 
181  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
182  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
183  {
184  Ipv6EndPoint* endP = *i;
185 
186  NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
187  << " daddr=" << endP->GetLocalAddress ()
188  << " sport=" << endP->GetPeerPort ()
189  << " saddr=" << endP->GetPeerAddress ());
190 
191  if (!endP->IsRxEnabled ())
192  {
193  NS_LOG_LOGIC ("Skipping endpoint " << &endP
194  << " because endpoint can not receive packets");
195  continue;
196  }
197 
198  if (endP->GetLocalPort () != dport)
199  {
200  NS_LOG_LOGIC ("Skipping endpoint " << &endP
201  << " because endpoint dport "
202  << endP->GetLocalPort ()
203  << " does not match packet dport " << dport);
204  continue;
205  }
206 
207  if (endP->GetBoundNetDevice ())
208  {
209  if (!incomingInterface)
210  {
211  continue;
212  }
213  if (endP->GetBoundNetDevice () != incomingInterface->GetDevice ())
214  {
215  NS_LOG_LOGIC ("Skipping endpoint " << &endP
216  << " because endpoint is bound to specific device and"
217  << endP->GetBoundNetDevice ()
218  << " does not match packet device " << incomingInterface->GetDevice ());
219  continue;
220  }
221  }
222 
223  /* Ipv6Address incomingInterfaceAddr = incomingInterface->GetAddress (); */
224  NS_LOG_DEBUG ("dest addr " << daddr);
225 
226  bool localAddressMatchesWildCard = endP->GetLocalAddress () == Ipv6Address::GetAny ();
227  bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
228  bool localAddressMatchesAllRouters = endP->GetLocalAddress () == Ipv6Address::GetAllRoutersMulticast ();
229 
230  /* if no match here, keep looking */
231  if (!(localAddressMatchesExact || localAddressMatchesWildCard))
232  {
233  continue;
234  }
235  bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
236  bool remotePeerMatchesWildCard = endP->GetPeerPort () == 0;
237  bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
238  bool remoteAddressMatchesWildCard = endP->GetPeerAddress () == Ipv6Address::GetAny ();
239 
240  /* If remote does not match either with exact or wildcard,i
241  skip this one */
242  if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
243  {
244  continue;
245  }
246  if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
247  {
248  continue;
249  }
250 
251  /* Now figure out which return list to add this one to */
252  if (localAddressMatchesWildCard
253  && remotePeerMatchesWildCard
254  && remoteAddressMatchesWildCard)
255  { /* Only local port matches exactly */
256  retval1.push_back (endP);
257  }
258  if ((localAddressMatchesExact || (localAddressMatchesAllRouters))
259  && remotePeerMatchesWildCard
260  && remoteAddressMatchesWildCard)
261  { /* Only local port and local address matches exactly */
262  retval2.push_back (endP);
263  }
264  if (localAddressMatchesWildCard
265  && remotePeerMatchesExact
266  && remoteAddressMatchesExact)
267  { /* All but local address */
268  retval3.push_back (endP);
269  }
270  if (localAddressMatchesExact
271  && remotePeerMatchesExact
272  && remoteAddressMatchesExact)
273  { /* All 4 match */
274  retval4.push_back (endP);
275  }
276  }
277 
278  /* Here we find the most exact match */
279  if (!retval4.empty ())
280  {
281  return retval4;
282  }
283  if (!retval3.empty ())
284  {
285  return retval3;
286  }
287  if (!retval2.empty ())
288  {
289  return retval2;
290  }
291  return retval1; /* might be empty if no matches */
292 }
293 
294 Ipv6EndPoint* Ipv6EndPointDemux::SimpleLookup (Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
295 {
296  uint32_t genericity = 3;
297  Ipv6EndPoint *generic = 0;
298 
299  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
300  {
301  uint32_t tmp = 0;
302 
303  if ((*i)->GetLocalPort () != dport)
304  {
305  continue;
306  }
307 
308  if ((*i)->GetLocalAddress () == dst && (*i)->GetPeerPort () == sport
309  && (*i)->GetPeerAddress () == src)
310  {
311  /* this is an exact match. */
312  return *i;
313  }
314 
315  if ((*i)->GetLocalAddress () == Ipv6Address::GetAny ())
316  {
317  tmp++;
318  }
319 
320  if ((*i)->GetPeerAddress () == Ipv6Address::GetAny ())
321  {
322  tmp++;
323  }
324 
325  if (tmp < genericity)
326  {
327  generic = (*i);
328  genericity = tmp;
329  }
330  }
331  return generic;
332 }
333 
335 {
337  uint16_t port = m_ephemeral;
338  int count = m_portLast - m_portFirst;
339  do
340  {
341  if (count-- < 0)
342  {
343  return 0;
344  }
345  ++port;
346  if (port < m_portFirst || port > m_portLast)
347  {
348  port = m_portFirst;
349  }
350  }
351  while (LookupPortLocal (port));
352  m_ephemeral = port;
353  return port;
354 }
355 
357 {
358  return m_endPoints;
359 }
360 
361 } /* namespace ns3 */
362 
Ipv6Address GetLocalAddress()
Get the local address.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
std::list< Ipv6EndPoint * > EndPoints
Container of the IPv6 endpoints.
EndPoints Lookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport, Ptr< Ipv6Interface > incomingInterface)
lookup for a match with all the parameters.
uint16_t m_ephemeral
The ephemeral port.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
std::list< Ipv6EndPoint * >::iterator EndPointsI
Iterator to the container of the IPv6 endpoints.
EndPoints m_endPoints
A list of IPv6 end points.
bool LookupLocal(Ipv6Address addr, uint16_t port)
Lookup for address and port.
uint16_t port
Definition: dsdv-manet.cc:44
uint16_t GetPeerPort()
Get the peer port.
uint16_t GetLocalPort()
Get the local port.
Ipv6EndPoint * Allocate(void)
Allocate a Ipv6EndPoint.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
uint16_t m_portLast
The last ephemeral port.
void DeAllocate(Ipv6EndPoint *endPoint)
Remove a end point.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool LookupPortLocal(uint16_t port)
Lookup for port local.
Ipv6EndPoint * SimpleLookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
Simple lookup for a four-tuple match.
bool IsRxEnabled(void)
Checks if the endpoint can receive packets.
uint16_t m_portFirst
The first ephemeral port.
Describes an IPv6 address.
Definition: ipv6-address.h:48
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:228
Ipv6Address GetPeerAddress()
Get the peer address.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
A representation of an IPv6 endpoint/connection.
tuple address
Definition: first.py:37
uint16_t AllocateEphemeralPort()
Allocate a ephemeral port.
Ptr< NetDevice > GetBoundNetDevice(void)
Returns socket's bound netdevice, if any.
EndPoints GetEndPoints() const
Get the entire list of end points registered.
void SetPeer(Ipv6Address addr, uint16_t port)
Set the peer informations (address and port).
static Ipv6Address GetAllRoutersMulticast()
Get the "all routers multicast" address.