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 {
34  NS_LOG_FUNCTION (this);
35 }
36 
38 {
39  NS_LOG_FUNCTION (this);
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 
61 bool Ipv6EndPointDemux::LookupLocal (Ptr<NetDevice> boundNetDevice, Ipv6Address addr, uint16_t port)
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  (*i)->GetBoundNetDevice () == boundNetDevice)
69  {
70  return true;
71  }
72  }
73  return false;
74 }
75 
77 {
78  NS_LOG_FUNCTION (this);
79  uint16_t port = AllocateEphemeralPort ();
80  if (port == 0)
81  {
82  NS_LOG_WARN ("Ephemeral port allocation failed.");
83  return 0;
84  }
85  Ipv6EndPoint *endPoint = new Ipv6EndPoint (Ipv6Address::GetAny (), port);
86  m_endPoints.push_back (endPoint);
87  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
88  return endPoint;
89 }
90 
92 {
93  NS_LOG_FUNCTION (this << address);
94  uint16_t port = AllocateEphemeralPort ();
95  if (port == 0)
96  {
97  NS_LOG_WARN ("Ephemeral port allocation failed.");
98  return 0;
99  }
100  Ipv6EndPoint *endPoint = new Ipv6EndPoint (address, port);
101  m_endPoints.push_back (endPoint);
102  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
103  return endPoint;
104 }
105 
107 {
108  NS_LOG_FUNCTION (this << boundNetDevice << port);
109 
110  return Allocate (boundNetDevice, Ipv6Address::GetAny (), port);
111 }
112 
114 {
115  NS_LOG_FUNCTION (this << boundNetDevice << address << port);
116  if (LookupLocal (boundNetDevice, address, port) || LookupLocal (0, address, port))
117  {
118  NS_LOG_WARN ("Duplicated endpoint.");
119  return 0;
120  }
121  Ipv6EndPoint *endPoint = new Ipv6EndPoint (address, port);
122  m_endPoints.push_back (endPoint);
123  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
124  return endPoint;
125 }
126 
128  Ipv6Address localAddress, uint16_t localPort,
129  Ipv6Address peerAddress, uint16_t peerPort)
130 {
131  NS_LOG_FUNCTION (this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
132  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
133  {
134  if ((*i)->GetLocalPort () == localPort &&
135  (*i)->GetLocalAddress () == localAddress &&
136  (*i)->GetPeerPort () == peerPort &&
137  (*i)->GetPeerAddress () == peerAddress &&
138  ((*i)->GetBoundNetDevice () == boundNetDevice || (*i)->GetBoundNetDevice () == 0))
139  {
140  NS_LOG_WARN ("Duplicated endpoint.");
141  return 0;
142  }
143  }
144  Ipv6EndPoint *endPoint = new Ipv6EndPoint (localAddress, localPort);
145  endPoint->SetPeer (peerAddress, peerPort);
146  m_endPoints.push_back (endPoint);
147 
148  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
149 
150  return endPoint;
151 }
152 
154 {
155  NS_LOG_FUNCTION (this);
156  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
157  {
158  if (*i == endPoint)
159  {
160  delete endPoint;
161  m_endPoints.erase (i);
162  break;
163  }
164  }
165 }
166 
167 /*
168  * If we have an exact match, we return it.
169  * Otherwise, if we find a generic match, we return it.
170  * Otherwise, we return 0.
171  */
173  Ipv6Address saddr, uint16_t sport,
174  Ptr<Ipv6Interface> incomingInterface)
175 {
176  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface);
177 
178  EndPoints retval1; /* Matches exact on local port, wildcards on others */
179  EndPoints retval2; /* Matches exact on local port/adder, wildcards on others */
180  EndPoints retval3; /* Matches all but local address */
181  EndPoints retval4; /* Exact match on all 4 */
182 
183  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
184  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
185  {
186  Ipv6EndPoint* endP = *i;
187 
188  NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
189  << " daddr=" << endP->GetLocalAddress ()
190  << " sport=" << endP->GetPeerPort ()
191  << " saddr=" << endP->GetPeerAddress ());
192 
193  if (!endP->IsRxEnabled ())
194  {
195  NS_LOG_LOGIC ("Skipping endpoint " << &endP
196  << " because endpoint can not receive packets");
197  continue;
198  }
199 
200  if (endP->GetLocalPort () != dport)
201  {
202  NS_LOG_LOGIC ("Skipping endpoint " << &endP
203  << " because endpoint dport "
204  << endP->GetLocalPort ()
205  << " does not match packet dport " << dport);
206  continue;
207  }
208 
209  if (endP->GetBoundNetDevice ())
210  {
211  if (!incomingInterface)
212  {
213  continue;
214  }
215  if (endP->GetBoundNetDevice () != incomingInterface->GetDevice ())
216  {
217  NS_LOG_LOGIC ("Skipping endpoint " << &endP
218  << " because endpoint is bound to specific device and"
219  << endP->GetBoundNetDevice ()
220  << " does not match packet device " << incomingInterface->GetDevice ());
221  continue;
222  }
223  }
224 
225  /* Ipv6Address incomingInterfaceAddr = incomingInterface->GetAddress (); */
226  NS_LOG_DEBUG ("dest addr " << daddr);
227 
228  bool localAddressMatchesWildCard = endP->GetLocalAddress () == Ipv6Address::GetAny ();
229  bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
230  bool localAddressMatchesAllRouters = endP->GetLocalAddress () == Ipv6Address::GetAllRoutersMulticast ();
231 
232  /* if no match here, keep looking */
233  if (!(localAddressMatchesExact || localAddressMatchesWildCard))
234  {
235  continue;
236  }
237  bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
238  bool remotePeerMatchesWildCard = endP->GetPeerPort () == 0;
239  bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
240  bool remoteAddressMatchesWildCard = endP->GetPeerAddress () == Ipv6Address::GetAny ();
241 
242  /* If remote does not match either with exact or wildcard,i
243  skip this one */
244  if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
245  {
246  continue;
247  }
248  if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
249  {
250  continue;
251  }
252 
253  /* Now figure out which return list to add this one to */
254  if (localAddressMatchesWildCard
255  && remotePeerMatchesWildCard
256  && remoteAddressMatchesWildCard)
257  { /* Only local port matches exactly */
258  retval1.push_back (endP);
259  }
260  if ((localAddressMatchesExact || (localAddressMatchesAllRouters))
261  && remotePeerMatchesWildCard
262  && remoteAddressMatchesWildCard)
263  { /* Only local port and local address matches exactly */
264  retval2.push_back (endP);
265  }
266  if (localAddressMatchesWildCard
267  && remotePeerMatchesExact
268  && remoteAddressMatchesExact)
269  { /* All but local address */
270  retval3.push_back (endP);
271  }
272  if (localAddressMatchesExact
273  && remotePeerMatchesExact
274  && remoteAddressMatchesExact)
275  { /* All 4 match */
276  retval4.push_back (endP);
277  }
278  }
279 
280  // Here we find the most exact match
281  EndPoints retval;
282  if (!retval4.empty ()) retval = retval4;
283  else if (!retval3.empty ()) retval = retval3;
284  else if (!retval2.empty ()) retval = retval2;
285  else retval = retval1;
286 
287  NS_ABORT_MSG_IF (retval.size () > 1, "Too many endpoints - perhaps you created too many sockets without binding them to different NetDevices.");
288  return retval; // might be empty if no matches
289 }
290 
291 Ipv6EndPoint* Ipv6EndPointDemux::SimpleLookup (Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
292 {
293  uint32_t genericity = 3;
294  Ipv6EndPoint *generic = 0;
295 
296  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
297  {
298  uint32_t tmp = 0;
299 
300  if ((*i)->GetLocalPort () != dport)
301  {
302  continue;
303  }
304 
305  if ((*i)->GetLocalAddress () == dst && (*i)->GetPeerPort () == sport
306  && (*i)->GetPeerAddress () == src)
307  {
308  /* this is an exact match. */
309  return *i;
310  }
311 
312  if ((*i)->GetLocalAddress () == Ipv6Address::GetAny ())
313  {
314  tmp++;
315  }
316 
317  if ((*i)->GetPeerAddress () == Ipv6Address::GetAny ())
318  {
319  tmp++;
320  }
321 
322  if (tmp < genericity)
323  {
324  generic = (*i);
325  genericity = tmp;
326  }
327  }
328  return generic;
329 }
330 
332 {
333  NS_LOG_FUNCTION (this);
334  uint16_t port = m_ephemeral;
335  int count = m_portLast - m_portFirst;
336  do
337  {
338  if (count-- < 0)
339  {
340  return 0;
341  }
342  ++port;
343  if (port < m_portFirst || port > m_portLast)
344  {
345  port = m_portFirst;
346  }
347  }
348  while (LookupPortLocal (port));
349  m_ephemeral = port;
350  return port;
351 }
352 
354 {
355  return m_endPoints;
356 }
357 
358 } /* namespace ns3 */
359 
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.
bool LookupLocal(Ptr< NetDevice > boundNetDevice, Ipv6Address addr, uint16_t port)
Lookup for address and port.
std::list< Ipv6EndPoint * > EndPoints
Container of the IPv6 endpoints.
EndPoints m_endPoints
A list of IPv6 end points.
uint16_t m_ephemeral
The ephemeral port.
Ipv6EndPoint * Allocate(void)
Allocate a Ipv6EndPoint.
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.
A representation of an IPv6 endpoint/connection.
Ipv6Address GetLocalAddress()
Get the local address.
void SetPeer(Ipv6Address addr, uint16_t port)
Set the peer information (address and port).
uint16_t GetLocalPort()
Get the local port.
Ptr< NetDevice > GetBoundNetDevice(void)
Returns socket's bound netdevice, if any.
bool IsRxEnabled(void)
Checks if the endpoint can receive packets.
Ipv6Address GetPeerAddress()
Get the peer address.
uint16_t GetPeerPort()
Get the peer port.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
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:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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:265
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.