A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
packet-socket.cc
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
39 PacketSocket::GetTypeId (void)
40 {
41  static TypeId tid = TypeId ("ns3::PacketSocket")
42  .SetParent<Socket> ()
43  .AddConstructor<PacketSocket> ()
44  .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
45  MakeTraceSourceAccessor (&PacketSocket::m_dropTrace))
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);
58  m_state = STATE_OPEN;
59  m_shutdownSend = false;
60  m_shutdownRecv = false;
61  m_errno = ERROR_NOTERROR;
62  m_isSingleDevice = false;
63  m_device = 0;
64 }
65 
66 void
67 PacketSocket::SetNode (Ptr<Node> node)
68 {
69  NS_LOG_FUNCTION (this << node);
70  m_node = node;
71 }
72 
73 PacketSocket::~PacketSocket ()
74 {
75  NS_LOG_FUNCTION (this);
76 }
77 
78 void
80 {
81  NS_LOG_FUNCTION (this);
82  m_device = 0;
83 }
84 
85 enum Socket::SocketErrno
87 {
88  NS_LOG_FUNCTION (this);
89  return m_errno;
90 }
91 
92 enum Socket::SocketType
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  {
129  m_errno = ERROR_INVAL;
130  return -1;
131  }
133  return DoBind (ad);
134 }
135 
136 int
137 PacketSocket::DoBind (const PacketSocketAddress &address)
138 {
139  NS_LOG_FUNCTION (this << address);
140  if (m_state == STATE_BOUND ||
141  m_state == STATE_CONNECTED)
142  {
143  m_errno = ERROR_INVAL;
144  return -1;
145  }
146  if (m_state == STATE_CLOSED)
147  {
148  m_errno = ERROR_BADF;
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  }
160  m_node->RegisterProtocolHandler (MakeCallback (&PacketSocket::ForwardUp, this),
161  address.GetProtocol (), dev);
162  m_state = STATE_BOUND;
163  m_protocol = address.GetProtocol ();
164  m_isSingleDevice = address.IsSingleDevice ();
165  m_device = address.GetSingleDevice ();
166  m_boundnetdevice = dev;
167  return 0;
168 }
169 
170 int
172 {
173  NS_LOG_FUNCTION (this);
174  if (m_state == STATE_CLOSED)
175  {
176  m_errno = ERROR_BADF;
177  return -1;
178  }
179  m_shutdownSend = true;
180  return 0;
181 }
182 
183 int
185 {
186  NS_LOG_FUNCTION (this);
187  if (m_state == STATE_CLOSED)
188  {
189  m_errno = ERROR_BADF;
190  return -1;
191  }
192  m_shutdownRecv = true;
193  return 0;
194 }
195 
196 int
198 {
199  NS_LOG_FUNCTION (this);
200  if (m_state == STATE_CLOSED)
201  {
202  m_errno = ERROR_BADF;
203  return -1;
204  }
205  else if (m_state == STATE_BOUND || m_state == STATE_CONNECTED)
206  {
207  m_node->UnregisterProtocolHandler (MakeCallback (&PacketSocket::ForwardUp, this));
208  }
209  m_state = STATE_CLOSED;
210  m_shutdownSend = true;
211  m_shutdownRecv = true;
212  return 0;
213 }
214 
215 int
217 {
218  NS_LOG_FUNCTION (this << ad);
219  PacketSocketAddress address;
220  if (m_state == STATE_CLOSED)
221  {
222  m_errno = ERROR_BADF;
223  goto error;
224  }
225  if (m_state == STATE_OPEN)
226  {
227  // connect should happen _after_ bind.
228  m_errno = ERROR_INVAL; // generic error condition.
229  goto error;
230  }
231  if (m_state == STATE_CONNECTED)
232  {
233  m_errno = ERROR_ISCONN;
234  goto error;
235  }
237  {
238  m_errno = ERROR_AFNOSUPPORT;
239  goto error;
240  }
241  m_destAddr = ad;
242  m_state = STATE_CONNECTED;
243  NotifyConnectionSucceeded ();
244  return 0;
245 error:
246  NotifyConnectionFailed ();
247  return -1;
248 }
249 int
251 {
252  NS_LOG_FUNCTION (this);
253  m_errno = Socket::ERROR_OPNOTSUPP;
254  return -1;
255 }
256 
257 int
258 PacketSocket::Send (Ptr<Packet> p, uint32_t flags)
259 {
260  NS_LOG_FUNCTION (this << p << flags);
261  if (m_state == STATE_OPEN ||
262  m_state == STATE_BOUND)
263  {
264  m_errno = ERROR_NOTCONN;
265  return -1;
266  }
267  return SendTo (p, flags, m_destAddr);
268 }
269 
270 uint32_t
271 PacketSocket::GetMinMtu (PacketSocketAddress ad) const
272 {
273  NS_LOG_FUNCTION (this << ad);
274  if (ad.IsSingleDevice ())
275  {
276  Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
277  return device->GetMtu ();
278  }
279  else
280  {
281  uint32_t minMtu = 0xffff;
282  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
283  {
284  Ptr<NetDevice> device = m_node->GetDevice (i);
285  minMtu = std::min (minMtu, (uint32_t)device->GetMtu ());
286  }
287  return minMtu;
288  }
289 }
290 
291 uint32_t
293 {
294  NS_LOG_FUNCTION (this);
295  if (m_state == STATE_CONNECTED)
296  {
298  return GetMinMtu (ad);
299  }
300  // If we are not connected, we return a 'safe' value by default.
301  return 0xffff;
302 }
303 
304 int
305 PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
306 {
307  NS_LOG_FUNCTION (this << p << flags << address);
309  if (m_state == STATE_CLOSED)
310  {
311  NS_LOG_LOGIC ("ERROR_BADF");
312  m_errno = ERROR_BADF;
313  return -1;
314  }
315  if (m_shutdownSend)
316  {
317  NS_LOG_LOGIC ("ERROR_SHUTDOWN");
318  m_errno = ERROR_SHUTDOWN;
319  return -1;
320  }
322  {
323  NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
324  m_errno = ERROR_AFNOSUPPORT;
325  return -1;
326  }
327  ad = PacketSocketAddress::ConvertFrom (address);
328  if (p->GetSize () > GetMinMtu (ad))
329  {
330  m_errno = ERROR_MSGSIZE;
331  return -1;
332  }
333 
334  bool error = false;
335  Address dest = ad.GetPhysicalAddress ();
336  if (ad.IsSingleDevice ())
337  {
338  Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
339  if (!device->Send (p, dest, ad.GetProtocol ()))
340  {
341  NS_LOG_LOGIC ("error: NetDevice::Send error");
342  error = true;
343  }
344  }
345  else
346  {
347  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
348  {
349  Ptr<NetDevice> device = m_node->GetDevice (i);
350  if (!device->Send (p, dest, ad.GetProtocol ()))
351  {
352  NS_LOG_LOGIC ("error: NetDevice::Send error");
353  error = true;
354  }
355  }
356  }
357  if (!error)
358  {
359  NotifyDataSent (p->GetSize ());
360  NotifySend (GetTxAvailable ());
361  }
362 
363  if (error)
364  {
365  NS_LOG_LOGIC ("ERROR_INVAL 2");
366  m_errno = ERROR_INVAL;
367  return -1;
368  }
369  else
370  {
371  return p->GetSize ();
372  }
373 }
374 
375 void
376 PacketSocket::ForwardUp (Ptr<NetDevice> device, Ptr<const Packet> packet,
377  uint16_t protocol, const Address &from,
378  const Address &to, NetDevice::PacketType packetType)
379 {
380  NS_LOG_FUNCTION (this << device << packet << protocol << from << to << packetType);
381  if (m_shutdownRecv)
382  {
383  return;
384  }
385  PacketSocketAddress address;
386  address.SetPhysicalAddress (from);
387  address.SetSingleDevice (device->GetIfIndex ());
388  address.SetProtocol (protocol);
389 
390  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
391  {
392  Ptr<Packet> copy = packet->Copy ();
393  DeviceNameTag dnt;
394  dnt.SetDeviceName (device->GetTypeId ().GetName ());
395  PacketSocketTag pst;
396  pst.SetPacketType (packetType);
397  pst.SetDestAddress (to);
398  SocketAddressTag tag;
399  tag.SetAddress (address);
400  copy->AddPacketTag (tag); // Attach From Physical Address
401  copy->AddPacketTag (pst); // Attach Packet Type and Dest Address
402  copy->AddPacketTag (dnt); // Attach device source name
403  m_deliveryQueue.push (copy);
404  m_rxAvailable += packet->GetSize ();
405  NS_LOG_LOGIC ("UID is " << packet->GetUid () << " PacketSocket " << this);
406  NotifyDataRecv ();
407  }
408  else
409  {
410  // In general, this case should not occur unless the
411  // receiving application reads data from this socket slowly
412  // in comparison to the arrival rate
413  //
414  // drop and trace packet
415  NS_LOG_WARN ("No receive buffer space available. Drop.");
416  m_dropTrace (packet);
417  }
418 }
419 
420 uint32_t
422 {
423  NS_LOG_FUNCTION (this);
424  // We separately maintain this state to avoid walking the queue
425  // every time this might be called
426  return m_rxAvailable;
427 }
428 
430 PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
431 {
432  NS_LOG_FUNCTION (this << maxSize << flags);
433  if (m_deliveryQueue.empty () )
434  {
435  return 0;
436  }
437  Ptr<Packet> p = m_deliveryQueue.front ();
438  if (p->GetSize () <= maxSize)
439  {
440  m_deliveryQueue.pop ();
441  m_rxAvailable -= p->GetSize ();
442  }
443  else
444  {
445  p = 0;
446  }
447  return p;
448 }
449 
451 PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
452 {
453  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
454  Ptr<Packet> packet = Recv (maxSize, flags);
455  if (packet != 0)
456  {
457  SocketAddressTag tag;
458  bool found;
459  found = packet->PeekPacketTag (tag);
460  NS_ASSERT (found);
461  fromAddress = tag.GetAddress ();
462  }
463  return packet;
464 }
465 
466 int
468 {
469  NS_LOG_FUNCTION (this << address);
471 
472  ad.SetProtocol (m_protocol);
473  if (m_isSingleDevice)
474  {
475  Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
476  ad.SetPhysicalAddress (device->GetAddress ());
477  ad.SetSingleDevice (m_device);
478  }
479  else
480  {
481  ad.SetPhysicalAddress (Address ());
482  ad.SetAllDevices ();
483  }
484  address = ad;
485 
486  return 0;
487 }
488 
489 bool
490 PacketSocket::SetAllowBroadcast (bool allowBroadcast)
491 {
492  NS_LOG_FUNCTION (this << allowBroadcast);
493  if (allowBroadcast)
494  {
495  return false;
496  }
497  return true;
498 }
499 
500 bool
502 {
503  NS_LOG_FUNCTION (this);
504  return false;
505 }
506 
507 /***************************************************************
508  * PacketSocket Tags
509  ***************************************************************/
510 
512 {
513 }
514 
515 void
517 {
518  m_packetType = t;
519 }
520 
523 {
524  return m_packetType;
525 }
526 
527 void
529 {
530  m_destAddr = a;
531 }
532 
533 Address
535 {
536  return m_destAddr;
537 }
538 
539 NS_OBJECT_ENSURE_REGISTERED (PacketSocketTag);
540 
541 TypeId
542 PacketSocketTag::GetTypeId (void)
543 {
544  static TypeId tid = TypeId ("ns3::PacketSocketTag")
545  .SetParent<Tag> ()
546  .AddConstructor<PacketSocketTag> ()
547  ;
548  return tid;
549 }
550 TypeId
552 {
553  return GetTypeId ();
554 }
555 uint32_t
557 {
558  return 1 + m_destAddr.GetSerializedSize();
559 }
560 void
562 {
563  i.WriteU8 (m_packetType);
564  m_destAddr.Serialize (i);
565 }
566 void
568 {
569  m_packetType = (NetDevice::PacketType) i.ReadU8 ();
570  m_destAddr.Deserialize (i);
571 }
572 void
573 PacketSocketTag::Print (std::ostream &os) const
574 {
575  os << "packetType=" << m_packetType;
576 }
577 
578 /***************************************************************
579  * DeviceName Tags
580  ***************************************************************/
581 
583 {
584 }
585 
586 void
588 {
589  if ( n.substr(0,5) == "ns3::" )
590  {
591  n = n.substr (5);
592  }
593  m_deviceName = n;
594 }
595 
596 std::string
598 {
599  return m_deviceName;
600 }
601 
602 NS_OBJECT_ENSURE_REGISTERED (DeviceNameTag);
603 
604 TypeId
605 DeviceNameTag::GetTypeId (void)
606 {
607  static TypeId tid = TypeId ("ns3::DeviceNameTag")
608  .SetParent<Tag> ()
609  .AddConstructor<DeviceNameTag> ();
610  return tid;
611 }
612 TypeId
614 {
615  return GetTypeId ();
616 }
617 uint32_t
619 {
620  uint32_t s = 1 + m_deviceName.size();
621  return ( s >= PACKET_TAG_MAX_SIZE)?PACKET_TAG_MAX_SIZE:s;
622 }
623 void
625 {
626  const char *n = m_deviceName.c_str();
627  uint8_t l = (uint8_t) strlen (n);
628 
629  if ( ( 1 + l ) > PACKET_TAG_MAX_SIZE ) l = PACKET_TAG_MAX_SIZE - 1;
630 
631  i.WriteU8 (l);
632  i.Write ( (uint8_t*) n , (uint32_t) l );
633 }
634 void
636 {
637  uint8_t l = i.ReadU8();
638  char buf[256];
639 
640  i.Read ( (uint8_t* ) buf, (uint32_t) l);
641  m_deviceName = std::string (buf, l);
642 }
643 void
644 DeviceNameTag::Print (std::ostream &os) const
645 {
646  os << "DeviceName=" << m_deviceName;
647 }
648 
649 
650 } // namespace ns3
void Write(const uint8_t *buffer, uint32_t size)
Definition: tag-buffer.cc:125
virtual enum SocketErrno GetErrno(void) const
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Address GetDestAddress(void) const
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:174
void AddPacketTag(const Tag &tag) const
Definition: packet.cc:868
uint64_t GetUid(void) const
Definition: packet.cc:412
std::queue< Ptr< Packet > > m_deliveryQueue
Default destination address.
an address for a packet socket
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
#define NS_ASSERT(condition)
Definition: assert.h:64
static bool IsMatchingType(const Address &address)
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual void DoDispose(void)
uint32_t GetSize(void) const
Definition: packet.h:620
virtual uint32_t GetSerializedSize(void) const
void SetPacketType(NetDevice::PacketType t)
virtual int Bind(void)
Allocate a local IPv4 endpoint for this socket.
virtual void Print(std::ostream &os) const
virtual int GetSockName(Address &address) const
void UnregisterProtocolHandler(ProtocolHandler handler)
Definition: node.cc:252
TAG_BUFFER_INLINE uint8_t ReadU8(void)
Definition: tag-buffer.h:179
a polymophic address class
Definition: address.h:86
virtual TypeId GetInstanceTypeId(void) const
virtual void Serialize(TagBuffer i) const
bool PeekPacketTag(Tag &tag) const
Definition: packet.cc:881
virtual bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
void SetDestAddress(Address a)
virtual int ShutdownRecv(void)
virtual void Deserialize(TagBuffer i)
virtual uint32_t GetSerializedSize(void) const
Ptr< NetDevice > GetDevice(uint32_t index) const
Definition: node.cc:133
This class implements a tag that carries an address of a packet across the socket interface...
Definition: socket.h:847
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
virtual Ptr< Node > GetNode(void) const
virtual int Listen(void)
Listen for incoming connections.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void Deserialize(TagBuffer buffer)
Definition: address.cc:162
uint32_t GetSerializedSize(void) const
Definition: address.cc:146
uint32_t GetNDevices(void) const
Definition: node.cc:141
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
virtual uint32_t GetRxAvailable(void) const
tag a set of bytes in a packet
Definition: tag.h:36
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send data to a specified peer.
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:156
This class implements a tag that carries the ns3 device name from where a packet is coming...
virtual bool GetAllowBroadcast() const
Query whether broadcast datagram transmissions are allowed.
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:218
virtual void Deserialize(TagBuffer i)
virtual int Close(void)
Close a socket.
#define PACKET_TAG_MAX_SIZE
Tag maximum size The maximum size (in bytes) of a Tag is stored in this constant. ...
read and write tag data
Definition: tag-buffer.h:51
void Serialize(TagBuffer buffer) const
Definition: address.cc:153
virtual uint32_t GetTxAvailable(void) const
Returns the number of bytes which can be sent in a single call to Send.
virtual void Serialize(TagBuffer i) const
#define NS_LOG_WARN(msg)
Definition: log.h:246
NetDevice::PacketType GetPacketType(void) const
virtual void Print(std::ostream &os) const
static PacketSocketAddress ConvertFrom(const Address &address)
virtual TypeId GetInstanceTypeId(void) const
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
void Read(uint8_t *buffer, uint32_t size)
Definition: tag-buffer.cc:176
virtual int Bind6(void)
Allocate a local IPv6 endpoint for this socket.
std::string GetDeviceName(void) const
This class implements a tag that carries the dest address of a packet and the packet type...
virtual int ShutdownSend(void)
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
virtual enum SocketType GetSocketType(void) const
void SetDeviceName(std::string n)