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  return NS3_SOCK_RAW;
96 }
97 
100 {
101  NS_LOG_FUNCTION (this);
102  return m_node;
103 }
104 
105 int
107 {
108  NS_LOG_FUNCTION (this);
109  PacketSocketAddress address;
110  address.SetProtocol (0);
111  address.SetAllDevices ();
112  return DoBind (address);
113 }
114 
115 int
117 {
118  return(Bind());
119 }
120 
121 int
122 PacketSocket::Bind (const Address &address)
123 {
124  NS_LOG_FUNCTION (this << address);
126  {
128  return -1;
129  }
131  return DoBind (ad);
132 }
133 
134 int
136 {
137  NS_LOG_FUNCTION (this << address);
138  if (m_state == STATE_BOUND ||
140  {
142  return -1;
143  }
144  if (m_state == STATE_CLOSED)
145  {
147  return -1;
148  }
149  Ptr<NetDevice> dev;
150  if (address.IsSingleDevice ())
151  {
152  dev = m_node->GetDevice (address.GetSingleDevice ());
153  }
154  else
155  {
156  dev = 0;
157  }
159  address.GetProtocol (), dev);
161  m_protocol = address.GetProtocol ();
162  m_isSingleDevice = address.IsSingleDevice ();
163  m_device = address.GetSingleDevice ();
164  return 0;
165 }
166 
167 int
169 {
170  NS_LOG_FUNCTION (this);
171  if (m_state == STATE_CLOSED)
172  {
174  return -1;
175  }
176  m_shutdownSend = true;
177  return 0;
178 }
179 
180 int
182 {
183  NS_LOG_FUNCTION (this);
184  if (m_state == STATE_CLOSED)
185  {
187  return -1;
188  }
189  m_shutdownRecv = true;
190  return 0;
191 }
192 
193 int
195 {
196  NS_LOG_FUNCTION (this);
197  if (m_state == STATE_CLOSED)
198  {
200  return -1;
201  }
202  else if (m_state == STATE_BOUND || m_state == STATE_CONNECTED)
203  {
205  }
207  m_shutdownSend = true;
208  m_shutdownRecv = true;
209  return 0;
210 }
211 
212 int
214 {
215  NS_LOG_FUNCTION (this << ad);
216  PacketSocketAddress address;
217  if (m_state == STATE_CLOSED)
218  {
220  goto error;
221  }
222  if (m_state == STATE_OPEN)
223  {
224  // connect should happen _after_ bind.
225  m_errno = ERROR_INVAL; // generic error condition.
226  goto error;
227  }
228  if (m_state == STATE_CONNECTED)
229  {
231  goto error;
232  }
234  {
236  goto error;
237  }
238  m_destAddr = ad;
241  return 0;
242 error:
244  return -1;
245 }
246 int
248 {
250  return -1;
251 }
252 
253 int
254 PacketSocket::Send (Ptr<Packet> p, uint32_t flags)
255 {
256  NS_LOG_FUNCTION (this << p << flags);
257  if (m_state == STATE_OPEN ||
258  m_state == STATE_BOUND)
259  {
261  return -1;
262  }
263  return SendTo (p, flags, m_destAddr);
264 }
265 
266 uint32_t
268 {
269  if (ad.IsSingleDevice ())
270  {
272  return device->GetMtu ();
273  }
274  else
275  {
276  uint32_t minMtu = 0xffff;
277  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
278  {
279  Ptr<NetDevice> device = m_node->GetDevice (i);
280  minMtu = std::min (minMtu, (uint32_t)device->GetMtu ());
281  }
282  return minMtu;
283  }
284 }
285 
286 uint32_t
288 {
289  if (m_state == STATE_CONNECTED)
290  {
292  return GetMinMtu (ad);
293  }
294  // If we are not connected, we return a 'safe' value by default.
295  return 0xffff;
296 }
297 
298 int
299 PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
300 {
301  NS_LOG_FUNCTION (this << p << flags << address);
303  if (m_state == STATE_CLOSED)
304  {
305  NS_LOG_LOGIC ("ERROR_BADF");
307  return -1;
308  }
309  if (m_shutdownSend)
310  {
311  NS_LOG_LOGIC ("ERROR_SHUTDOWN");
313  return -1;
314  }
316  {
317  NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
319  return -1;
320  }
321  ad = PacketSocketAddress::ConvertFrom (address);
322  if (p->GetSize () > GetMinMtu (ad))
323  {
325  return -1;
326  }
327 
328  bool error = false;
329  Address dest = ad.GetPhysicalAddress ();
330  if (ad.IsSingleDevice ())
331  {
333  if (!device->Send (p, dest, ad.GetProtocol ()))
334  {
335  NS_LOG_LOGIC ("error: NetDevice::Send error");
336  error = true;
337  }
338  }
339  else
340  {
341  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
342  {
343  Ptr<NetDevice> device = m_node->GetDevice (i);
344  if (!device->Send (p, dest, ad.GetProtocol ()))
345  {
346  NS_LOG_LOGIC ("error: NetDevice::Send error");
347  error = true;
348  }
349  }
350  }
351  if (!error)
352  {
353  NotifyDataSent (p->GetSize ());
355  }
356 
357  if (error)
358  {
359  NS_LOG_LOGIC ("ERROR_INVAL 2");
361  return -1;
362  }
363  else
364  {
365  return p->GetSize ();
366  }
367 }
368 
369 void
371  uint16_t protocol, const Address &from,
372  const Address &to, NetDevice::PacketType packetType)
373 {
374  NS_LOG_FUNCTION (this << device << packet << protocol << from << to << packetType);
375  if (m_shutdownRecv)
376  {
377  return;
378  }
379 
380 
381  PacketSocketAddress address;
382  address.SetPhysicalAddress (from);
383  address.SetSingleDevice (device->GetIfIndex ());
384  address.SetProtocol (protocol);
385 
386  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
387  {
388  Ptr<Packet> copy = packet->Copy ();
389  SocketAddressTag tag;
390  tag.SetAddress (address);
391  copy->AddPacketTag (tag);
392  m_deliveryQueue.push (copy);
393  m_rxAvailable += packet->GetSize ();
394  NS_LOG_LOGIC ("UID is " << packet->GetUid () << " PacketSocket " << this);
395  NotifyDataRecv ();
396  }
397  else
398  {
399  // In general, this case should not occur unless the
400  // receiving application reads data from this socket slowly
401  // in comparison to the arrival rate
402  //
403  // drop and trace packet
404  NS_LOG_WARN ("No receive buffer space available. Drop.");
405  m_dropTrace (packet);
406  }
407 }
408 
409 uint32_t
411 {
412  NS_LOG_FUNCTION (this);
413  // We separately maintain this state to avoid walking the queue
414  // every time this might be called
415  return m_rxAvailable;
416 }
417 
419 PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
420 {
421  NS_LOG_FUNCTION (this << maxSize << flags);
422  if (m_deliveryQueue.empty () )
423  {
424  return 0;
425  }
426  Ptr<Packet> p = m_deliveryQueue.front ();
427  if (p->GetSize () <= maxSize)
428  {
429  m_deliveryQueue.pop ();
430  m_rxAvailable -= p->GetSize ();
431  }
432  else
433  {
434  p = 0;
435  }
436  return p;
437 }
438 
440 PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
441 {
442  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
443  Ptr<Packet> packet = Recv (maxSize, flags);
444  if (packet != 0)
445  {
446  SocketAddressTag tag;
447  bool found;
448  found = packet->PeekPacketTag (tag);
449  NS_ASSERT (found);
450  fromAddress = tag.GetAddress ();
451  }
452  return packet;
453 }
454 
455 int
457 {
458  NS_LOG_FUNCTION (this << address);
460 
461  ad.SetProtocol (m_protocol);
462  if (m_isSingleDevice)
463  {
465  ad.SetPhysicalAddress (device->GetAddress ());
467  }
468  else
469  {
470  ad.SetPhysicalAddress (Address ());
471  ad.SetAllDevices ();
472  }
473  address = ad;
474 
475  return 0;
476 }
477 
478 bool
479 PacketSocket::SetAllowBroadcast (bool allowBroadcast)
480 {
481  if (allowBroadcast)
482  {
483  return false;
484  }
485  return true;
486 }
487 
488 bool
490 {
491  return false;
492 }
493 
494 } // namespace ns3