A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
packet-socket.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007 Emmanuelle Laprise, INRIA
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  * Authors: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
19  * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  */
21 
22 #include "packet-socket.h"
23 #include "packet-socket-address.h"
24 #include "ns3/log.h"
25 #include "ns3/node.h"
26 #include "ns3/packet.h"
27 #include "ns3/uinteger.h"
28 #include "ns3/trace-source-accessor.h"
29 
30 #include <algorithm>
31 
32 NS_LOG_COMPONENT_DEFINE ("PacketSocket");
33 
34 namespace ns3 {
35 
36 NS_OBJECT_ENSURE_REGISTERED (PacketSocket);
37 
38 TypeId
40 {
41  static TypeId tid = TypeId ("ns3::PacketSocket")
42  .SetParent<Socket> ()
43  .AddConstructor<PacketSocket> ()
44  .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
46  .AddAttribute ("RcvBufSize",
47  "PacketSocket maximum receive buffer size (bytes)",
48  UintegerValue (131072),
49  MakeUintegerAccessor (&PacketSocket::m_rcvBufSize),
50  MakeUintegerChecker<uint32_t> ())
51  ;
52  return tid;
53 }
54 
55 PacketSocket::PacketSocket () : m_rxAvailable (0)
56 {
57  NS_LOG_FUNCTION (this);
59  m_shutdownSend = false;
60  m_shutdownRecv = false;
62  m_isSingleDevice = false;
63  m_device = 0;
64 }
65 
66 void
68 {
69  NS_LOG_FUNCTION (this << node);
70  m_node = node;
71 }
72 
74 {
75  NS_LOG_FUNCTION (this);
76 }
77 
78 void
80 {
81  NS_LOG_FUNCTION (this);
82  m_device = 0;
83 }
84 
87 {
88  NS_LOG_FUNCTION (this);
89  return m_errno;
90 }
91 
94 {
95  NS_LOG_FUNCTION (this);
96  return NS3_SOCK_RAW;
97 }
98 
101 {
102  NS_LOG_FUNCTION (this);
103  return m_node;
104 }
105 
106 int
108 {
109  NS_LOG_FUNCTION (this);
110  PacketSocketAddress address;
111  address.SetProtocol (0);
112  address.SetAllDevices ();
113  return DoBind (address);
114 }
115 
116 int
118 {
119  NS_LOG_FUNCTION (this);
120  return(Bind());
121 }
122 
123 int
124 PacketSocket::Bind (const Address &address)
125 {
126  NS_LOG_FUNCTION (this << address);
128  {
130  return -1;
131  }
133  return DoBind (ad);
134 }
135 
136 int
138 {
139  NS_LOG_FUNCTION (this << address);
140  if (m_state == STATE_BOUND ||
142  {
144  return -1;
145  }
146  if (m_state == STATE_CLOSED)
147  {
149  return -1;
150  }
151  Ptr<NetDevice> dev;
152  if (address.IsSingleDevice ())
153  {
154  dev = m_node->GetDevice (address.GetSingleDevice ());
155  }
156  else
157  {
158  dev = 0;
159  }
161  address.GetProtocol (), dev);
163  m_protocol = address.GetProtocol ();
164  m_isSingleDevice = address.IsSingleDevice ();
165  m_device = address.GetSingleDevice ();
166  return 0;
167 }
168 
169 int
171 {
172  NS_LOG_FUNCTION (this);
173  if (m_state == STATE_CLOSED)
174  {
176  return -1;
177  }
178  m_shutdownSend = true;
179  return 0;
180 }
181 
182 int
184 {
185  NS_LOG_FUNCTION (this);
186  if (m_state == STATE_CLOSED)
187  {
189  return -1;
190  }
191  m_shutdownRecv = true;
192  return 0;
193 }
194 
195 int
197 {
198  NS_LOG_FUNCTION (this);
199  if (m_state == STATE_CLOSED)
200  {
202  return -1;
203  }
204  else if (m_state == STATE_BOUND || m_state == STATE_CONNECTED)
205  {
207  }
209  m_shutdownSend = true;
210  m_shutdownRecv = true;
211  return 0;
212 }
213 
214 int
216 {
217  NS_LOG_FUNCTION (this << ad);
218  PacketSocketAddress address;
219  if (m_state == STATE_CLOSED)
220  {
222  goto error;
223  }
224  if (m_state == STATE_OPEN)
225  {
226  // connect should happen _after_ bind.
227  m_errno = ERROR_INVAL; // generic error condition.
228  goto error;
229  }
230  if (m_state == STATE_CONNECTED)
231  {
233  goto error;
234  }
236  {
238  goto error;
239  }
240  m_destAddr = ad;
243  return 0;
244 error:
246  return -1;
247 }
248 int
250 {
251  NS_LOG_FUNCTION (this);
253  return -1;
254 }
255 
256 int
257 PacketSocket::Send (Ptr<Packet> p, uint32_t flags)
258 {
259  NS_LOG_FUNCTION (this << p << flags);
260  if (m_state == STATE_OPEN ||
261  m_state == STATE_BOUND)
262  {
264  return -1;
265  }
266  return SendTo (p, flags, m_destAddr);
267 }
268 
269 uint32_t
271 {
272  NS_LOG_FUNCTION (this << ad);
273  if (ad.IsSingleDevice ())
274  {
276  return device->GetMtu ();
277  }
278  else
279  {
280  uint32_t minMtu = 0xffff;
281  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
282  {
283  Ptr<NetDevice> device = m_node->GetDevice (i);
284  minMtu = std::min (minMtu, (uint32_t)device->GetMtu ());
285  }
286  return minMtu;
287  }
288 }
289 
290 uint32_t
292 {
293  NS_LOG_FUNCTION (this);
294  if (m_state == STATE_CONNECTED)
295  {
297  return GetMinMtu (ad);
298  }
299  // If we are not connected, we return a 'safe' value by default.
300  return 0xffff;
301 }
302 
303 int
304 PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
305 {
306  NS_LOG_FUNCTION (this << p << flags << address);
308  if (m_state == STATE_CLOSED)
309  {
310  NS_LOG_LOGIC ("ERROR_BADF");
312  return -1;
313  }
314  if (m_shutdownSend)
315  {
316  NS_LOG_LOGIC ("ERROR_SHUTDOWN");
318  return -1;
319  }
321  {
322  NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
324  return -1;
325  }
326  ad = PacketSocketAddress::ConvertFrom (address);
327  if (p->GetSize () > GetMinMtu (ad))
328  {
330  return -1;
331  }
332 
333  bool error = false;
334  Address dest = ad.GetPhysicalAddress ();
335  if (ad.IsSingleDevice ())
336  {
338  if (!device->Send (p, dest, ad.GetProtocol ()))
339  {
340  NS_LOG_LOGIC ("error: NetDevice::Send error");
341  error = true;
342  }
343  }
344  else
345  {
346  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
347  {
348  Ptr<NetDevice> device = m_node->GetDevice (i);
349  if (!device->Send (p, dest, ad.GetProtocol ()))
350  {
351  NS_LOG_LOGIC ("error: NetDevice::Send error");
352  error = true;
353  }
354  }
355  }
356  if (!error)
357  {
358  NotifyDataSent (p->GetSize ());
360  }
361 
362  if (error)
363  {
364  NS_LOG_LOGIC ("ERROR_INVAL 2");
366  return -1;
367  }
368  else
369  {
370  return p->GetSize ();
371  }
372 }
373 
374 void
376  uint16_t protocol, const Address &from,
377  const Address &to, NetDevice::PacketType packetType)
378 {
379  NS_LOG_FUNCTION (this << device << packet << protocol << from << to << packetType);
380  if (m_shutdownRecv)
381  {
382  return;
383  }
384 
385 
386  PacketSocketAddress address;
387  address.SetPhysicalAddress (from);
388  address.SetSingleDevice (device->GetIfIndex ());
389  address.SetProtocol (protocol);
390 
391  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
392  {
393  Ptr<Packet> copy = packet->Copy ();
394  SocketAddressTag tag;
395  tag.SetAddress (address);
396  copy->AddPacketTag (tag);
397  m_deliveryQueue.push (copy);
398  m_rxAvailable += packet->GetSize ();
399  NS_LOG_LOGIC ("UID is " << packet->GetUid () << " PacketSocket " << this);
400  NotifyDataRecv ();
401  }
402  else
403  {
404  // In general, this case should not occur unless the
405  // receiving application reads data from this socket slowly
406  // in comparison to the arrival rate
407  //
408  // drop and trace packet
409  NS_LOG_WARN ("No receive buffer space available. Drop.");
410  m_dropTrace (packet);
411  }
412 }
413 
414 uint32_t
416 {
417  NS_LOG_FUNCTION (this);
418  // We separately maintain this state to avoid walking the queue
419  // every time this might be called
420  return m_rxAvailable;
421 }
422 
424 PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
425 {
426  NS_LOG_FUNCTION (this << maxSize << flags);
427  if (m_deliveryQueue.empty () )
428  {
429  return 0;
430  }
431  Ptr<Packet> p = m_deliveryQueue.front ();
432  if (p->GetSize () <= maxSize)
433  {
434  m_deliveryQueue.pop ();
435  m_rxAvailable -= p->GetSize ();
436  }
437  else
438  {
439  p = 0;
440  }
441  return p;
442 }
443 
445 PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
446 {
447  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
448  Ptr<Packet> packet = Recv (maxSize, flags);
449  if (packet != 0)
450  {
451  SocketAddressTag tag;
452  bool found;
453  found = packet->PeekPacketTag (tag);
454  NS_ASSERT (found);
455  fromAddress = tag.GetAddress ();
456  }
457  return packet;
458 }
459 
460 int
462 {
463  NS_LOG_FUNCTION (this << address);
465 
466  ad.SetProtocol (m_protocol);
467  if (m_isSingleDevice)
468  {
470  ad.SetPhysicalAddress (device->GetAddress ());
472  }
473  else
474  {
475  ad.SetPhysicalAddress (Address ());
476  ad.SetAllDevices ();
477  }
478  address = ad;
479 
480  return 0;
481 }
482 
483 bool
484 PacketSocket::SetAllowBroadcast (bool allowBroadcast)
485 {
486  NS_LOG_FUNCTION (this << allowBroadcast);
487  if (allowBroadcast)
488  {
489  return false;
490  }
491  return true;
492 }
493 
494 bool
496 {
497  NS_LOG_FUNCTION (this);
498  return false;
499 }
500 
501 } // namespace ns3