ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
linux-socket-impl.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 NICT
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: Hajime Tazaki <tazaki@nict.go.jp>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/node.h"
23 #include "ns3/packet.h"
24 #include "ns3/uinteger.h"
25 #include "ns3/event-id.h"
27 #include "linux-socket-fd.h"
28 #include "linux-socket-impl.h"
29 #include "dce-manager.h"
30 #include "process.h"
31 #include "utils.h"
32 #include "file-usage.h"
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <poll.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <net/if.h>
39 #include "ns3/inet-socket-address.h"
40 #include "ns3/inet6-socket-address.h"
41 
42 NS_LOG_COMPONENT_DEFINE ("LinuxSocketImpl");
43 
44 namespace ns3 {
45 
46 NS_OBJECT_ENSURE_REGISTERED (LinuxSocketImpl);
47 
48 Address
49 LinuxSocketImpl::PosixAddressToNs3Address (const struct sockaddr *my_addr, socklen_t addrlen)
50 {
51  if (my_addr->sa_family == AF_INET)
52  {
53  const struct sockaddr_in *addr = (const struct sockaddr_in *)my_addr;
54  Ipv4Address ipv4;
55  ipv4.Set (ntohl (addr->sin_addr.s_addr));
56  uint16_t port = ntohs (addr->sin_port);
57  InetSocketAddress inet = InetSocketAddress (ipv4, port);
58  return inet;
59  }
60  else if (my_addr->sa_family == AF_INET6)
61  {
62  const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)my_addr;
63  Ipv6Address ipv6;
64  ipv6.Set ((uint8_t *)addr->sin6_addr.s6_addr);
65  uint16_t port = ntohs (addr->sin6_port);
66  Inet6SocketAddress inet = Inet6SocketAddress (ipv6, port);
67  return inet;
68  }
69  else
70  {
71  NS_LOG_WARN ("Unsupported address familiy");
72  }
73  return Address ();
74 }
75 
76 int
78  struct sockaddr *addr, socklen_t *addrlen)
79 {
80  if (addr == 0 || addrlen == 0)
81  {
82  return 0;
83  }
84  if (InetSocketAddress::IsMatchingType (nsaddr))
85  {
86  InetSocketAddress ns_inetaddr = InetSocketAddress::ConvertFrom (nsaddr);
87  if (*addrlen < sizeof (struct sockaddr_in))
88  {
89  return -1;
90  }
91  struct sockaddr_in *inet_addr = (struct sockaddr_in *)addr;
92  memset (inet_addr, 0, sizeof (struct sockaddr_in));
93  inet_addr->sin_family = AF_INET;
94  inet_addr->sin_port = htons (ns_inetaddr.GetPort ());
95  inet_addr->sin_addr.s_addr = htonl (ns_inetaddr.GetIpv4 ().Get ());
96  *addrlen = sizeof(struct sockaddr_in);
97  }
98  else if (Inet6SocketAddress::IsMatchingType (nsaddr))
99  {
100  Inet6SocketAddress ns_inetaddr = Inet6SocketAddress::ConvertFrom (nsaddr);
101  if (*addrlen < sizeof (struct sockaddr_in6))
102  {
103  return -1;
104  }
105  struct sockaddr_in6 *inet_addr = (struct sockaddr_in6 *)addr;
106  inet_addr->sin6_family = AF_INET;
107  inet_addr->sin6_port = htons (ns_inetaddr.GetPort ());
108  ns_inetaddr.GetIpv6 ().GetBytes (inet_addr->sin6_addr.s6_addr);
109  *addrlen = sizeof(struct sockaddr_in6);
110  }
111  else
112  {
113  NS_LOG_WARN ("Unsupported address familiy");
114  }
115  return 0;
116 }
117 
118 // Add attributes generic to all Sockets to base class Socket
119 TypeId
121 {
122  static TypeId tid = TypeId ("ns3::LinuxSocketImpl")
123  .SetParent<Socket> ()
124  .AddConstructor<LinuxSocketImpl> ()
125  .AddAttribute ("Family", "Protocol family.",
126  UintegerValue (0),
127  MakeUintegerAccessor (&LinuxSocketImpl::m_family),
128  MakeUintegerChecker<uint16_t> ())
129  .AddAttribute ("SockType", "Socket type.",
130  UintegerValue (0),
131  MakeUintegerAccessor (&LinuxSocketImpl::m_socktype),
132  MakeUintegerChecker<uint16_t> ())
133  .AddAttribute ("Protocol", "Protocol number to match.",
134  UintegerValue (0),
135  MakeUintegerAccessor (&LinuxSocketImpl::m_protocol),
136  MakeUintegerChecker<uint16_t> ())
137  ;
138  return tid;
139 }
140 
142 {
143  NS_LOG_FUNCTION_NOARGS ();
144  m_listening = false;
145  m_conn_inprogress = false;
146  m_pid = -1;
149 }
150 
152 {
153  if (m_poll.IsRunning ())
154  {
155  m_poll.Cancel ();
156  }
157  Ptr<Node> node = GetNode ();
158  Ptr<DceManager> manager = node->GetObject<DceManager> ();
159 }
160 
161 void
163 {
164  Task *current = TaskManager::Current ()->CurrentTask ();
165  LinuxSocketImpl *self = (LinuxSocketImpl *) current->GetExtraContext ();
166  current->SetExtraContext (0);
167  EventImpl *event = (EventImpl *)context;
168  event->Invoke ();
169  event->Unref ();
170  TaskManager::Current ()->Exit ();
171 }
172 
173 void
175 {
176  Ptr<Node> node = GetNode ();
177  Ptr<DceManager> manager = node->GetObject<DceManager> ();
178  Ptr<TaskManager> taskManager = this->GetObject<TaskManager> ();
179  std::vector<std::string> nullargs;
180  std::vector<std::pair<std::string,std::string> > envs;
181  struct Process *process = manager->CreateProcess ("dummy-task", "dummy-stdin", nullargs, envs, 0);
182  struct Thread *thread = manager->CreateThread (process);
184  event, 1 << 17);
185  task->SetContext (thread);
186  thread->task = task;
187  task->SetExtraContext (this);
188 }
189 
190 enum Socket::SocketErrno
192 {
193  NS_LOG_FUNCTION_NOARGS ();
194  return m_errno;
195 }
196 
197 enum Socket::SocketType
199 {
200  switch (m_socktype)
201  {
202  case SOCK_STREAM:
203  case SOCK_DCCP:
204  {
205  return NS3_SOCK_STREAM;
206  break;
207  }
208  case SOCK_DGRAM:
209  {
210  return NS3_SOCK_DGRAM;
211  break;
212  }
213  case SOCK_RAW:
214  {
215  return NS3_SOCK_RAW;
216  break;
217  }
218  default:
219  break;
220  }
221 }
222 
223 uint16_t
225 {
226  NS_LOG_FUNCTION (this << m_pid);
227  Ptr<Node> node = GetNode ();
228  Ptr<DceManager> manager = node->GetObject<DceManager> ();
229  if (m_pid == 65535)
230  {
231  m_pid = manager->StartTemporaryTask ();
232  }
233  else
234  {
235  manager->ResumeTemporaryTask (m_pid);
236  }
237  return m_pid;
238 }
239 
240 void
242 {
243  NS_LOG_FUNCTION (this << m_pid << pid);
244  Ptr<Node> node = GetNode ();
245  Ptr<DceManager> manager = node->GetObject<DceManager> ();
246  manager->SuspendTemporaryTask (pid);
247  return;
248 }
249 
250 
251 int
253 {
254  NS_LOG_FUNCTION_NOARGS ();
255  uint16_t pid = EnterFakeTask ();
256  int ret = this->m_kernsock->Bind (NULL, 0);
257  LeaveFakeTask (pid);
258  return ret;
259 }
260 
261 int
263 {
264  NS_LOG_FUNCTION_NOARGS ();
265  uint16_t pid = EnterFakeTask ();
266  int ret = this->m_kernsock->Bind (NULL, 0);
267  LeaveFakeTask (pid);
268  return ret;
269 }
270 
271 int
272 LinuxSocketImpl::Bind (const Address &address)
273 {
274  NS_LOG_FUNCTION (this << address);
275  uint16_t pid = EnterFakeTask ();
276  struct sockaddr_storage my_addr;
277  socklen_t addrlen = sizeof (my_addr);
278  m_ns3toposix (address, (struct sockaddr *)&my_addr, &addrlen);
279 
280  int ret = this->m_kernsock->Bind ((struct sockaddr *)&my_addr, addrlen);
281  LeaveFakeTask (pid);
282  return ret;
283 }
284 
285 int
287 {
288  NS_LOG_FUNCTION_NOARGS ();
289  return 0;
290 }
291 
292 int
294 {
295  NS_LOG_FUNCTION_NOARGS ();
296  return 0;
297 }
298 
299 int
301 {
302  NS_LOG_FUNCTION_NOARGS ();
303  uint16_t pid = EnterFakeTask ();
304  int ret = this->m_kernsock->Close ();
305  LeaveFakeTask (pid);
306  return ret;
307 }
308 
309 int
310 LinuxSocketImpl::Connect (const Address & address)
311 {
312  NS_LOG_FUNCTION (this << address);
313  uint16_t pid = EnterFakeTask ();
314  struct sockaddr_storage my_addr;
315  socklen_t addrlen = sizeof (my_addr);
316  m_ns3toposix (address, (struct sockaddr *)&my_addr, &addrlen);
317 
318  int ret = this->m_kernsock->Connect ((struct sockaddr *)&my_addr, addrlen);
319  NS_LOG_INFO ("connect returns " << ret << " errno " << Current ()->err);
320  if (ret == -1 && Current ()->err == EINPROGRESS)
321  {
322  m_conn_inprogress = true;
323  }
324  LeaveFakeTask (pid);
325  return ret;
326 }
327 
328 int
330 {
331  NS_LOG_FUNCTION (this);
332  uint16_t pid = EnterFakeTask ();
333  int ret = this->m_kernsock->Listen (5);
334  NS_LOG_DEBUG ("listen returns " << ret << " errno " << Current ()->err);
335  if (ret == 0)
336  {
337  m_listening = true;
338  }
339  LeaveFakeTask (pid);
340  return ret;
341 }
342 
343 int
344 LinuxSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
345 {
346  NS_LOG_FUNCTION (this << p << flags);
347  uint16_t pid = EnterFakeTask ();
348  uint8_t *buf = new uint8_t[p->GetSize ()];
349  p->CopyData (buf, p->GetSize ());
350  int len = p->GetSize ();
351 
352  int ret = this->m_kernsock->Write (buf, len);
353  if (ret < 0)
354  {
355  NS_LOG_INFO ("send returns " << ret << " errno " << Current ()->err);
356  }
357 
358  LeaveFakeTask (pid);
359  return ret;
360 }
361 
362 
363 // XXX maximum message size for UDP broadcast is limited by MTU
364 // size of underlying link; we are not checking that now.
365 uint32_t
367 {
368  NS_LOG_FUNCTION_NOARGS ();
369  // No finite send buffer is modelled, but we must respect
370  // the maximum size of an IP datagram (65535 bytes - headers).
371  return -1;
372 }
373 
374 int
375 LinuxSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
376 {
377  NS_LOG_FUNCTION (this << p << flags << address);
378  uint8_t *buf = new uint8_t[p->GetSize ()];
379  p->CopyData (buf, p->GetSize ());
380  int len = p->GetSize ();
381  struct sockaddr_storage my_addr;
382  socklen_t addrlen = sizeof (my_addr);
383  m_ns3toposix (address, (struct sockaddr *)&my_addr, &addrlen);
384 
385  struct msghdr msg;
386  struct iovec iov;
387  msg.msg_control = 0;
388  msg.msg_controllen = 0;
389  msg.msg_iovlen = 1;
390  msg.msg_iov = &iov;
391  iov.iov_len = len;
392  iov.iov_base = (void *)buf;
393  msg.msg_name = (void *)&my_addr;
394  msg.msg_namelen = addrlen;
395 
396  uint16_t pid = EnterFakeTask ();
397  int ret = this->m_kernsock->Sendmsg (&msg, flags);
398  if (ret < 0)
399  {
400  NS_LOG_INFO ("sendmsg returns " << ret << " errno " << Current ()->err);
401  }
402  LeaveFakeTask (pid);
403  return ret;
404 }
405 
406 uint32_t
408 {
409  NS_LOG_FUNCTION_NOARGS ();
410  // We separately maintain this state to avoid walking the queue
411  // every time this might be called
412  return -1;
413 }
414 
415 Ptr<Packet>
416 LinuxSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
417 {
418  NS_LOG_FUNCTION (this << maxSize << flags);
419  return 0;
420 }
421 
422 Ptr<Packet>
423 LinuxSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
424  Address &fromAddress)
425 {
426  NS_LOG_FUNCTION (this << maxSize << flags);
427  uint8_t buf[4096];
428  struct sockaddr_storage my_addr;
429  socklen_t addrlen = sizeof (struct sockaddr_storage);
430  struct msghdr msg;
431  struct iovec iov;
432  msg.msg_control = 0;
433  msg.msg_controllen = 0;
434  msg.msg_iovlen = 1;
435  msg.msg_iov = &iov;
436  iov.iov_len = sizeof (buf);
437  iov.iov_base = buf;
438  msg.msg_name = (void *)&my_addr;
439  msg.msg_namelen = addrlen;
440 
441  uint16_t pid = EnterFakeTask ();
442  int ret = this->m_kernsock->Recvmsg (&msg, flags);
443  if (ret < 0)
444  {
445  NS_LOG_DEBUG ("recvmsg ret " << ret << " errno " << Current ()->err);
446  LeaveFakeTask (pid);
447  return 0;
448  }
449  LeaveFakeTask (pid);
450 
451  Ptr<Packet> p = Create<Packet> (buf, ret);
452  pid = EnterFakeTask ();
453  ret = this->m_kernsock->Getpeername ((struct sockaddr *)&my_addr, &addrlen);
454  if (ret < 0)
455  {
456  NS_LOG_DEBUG ("getpeername ret " << ret);
457  }
458  LeaveFakeTask (pid);
459  fromAddress = m_posixtons3 ((struct sockaddr *)&my_addr, addrlen);
460 
461  return p;
462 }
463 
464 int
465 LinuxSocketImpl::GetSockName (Address &address) const
466 {
467  NS_LOG_FUNCTION_NOARGS ();
468  return -1;
469 }
470 
471 int
472 LinuxSocketImpl::MulticastJoinGroup (uint32_t interface, const Address &groupAddress)
473 {
474  NS_LOG_FUNCTION (interface << groupAddress);
475  /*
476  1) sanity check interface
477  2) sanity check that it has not been called yet on this interface/group
478  3) determine address family of groupAddress
479  4) locally store a list of (interface, groupAddress)
480  5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
481  */
482  return 0;
483 }
484 
485 int
486 LinuxSocketImpl::MulticastLeaveGroup (uint32_t interface, const Address &groupAddress)
487 {
488  NS_LOG_FUNCTION (interface << groupAddress);
489  /*
490  1) sanity check interface
491  2) determine address family of groupAddress
492  3) delete from local list of (interface, groupAddress); raise a LOG_WARN
493  if not already present (but return 0)
494  5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
495  */
496  return 0;
497 }
498 
499 void
500 LinuxSocketImpl::BindToNetDevice (Ptr<NetDevice> netdevice)
501 {
502  NS_LOG_FUNCTION (netdevice->GetIfIndex ());
503  std::ostringstream oss;
504  oss << "sim" << netdevice->GetIfIndex ();
505  struct ifreq ifr;
506  strncpy ((char *)&ifr.ifr_name, oss.str ().c_str (), sizeof (ifr.ifr_name));
507 
508  uint16_t pid = EnterFakeTask ();
509  int ret = this->m_kernsock->Setsockopt (SOL_SOCKET, SO_BINDTODEVICE,
510  &ifr, sizeof (ifr));
511  NS_LOG_INFO ("sockopt returns " << ret << " errno " << Current ()->err);
512  LeaveFakeTask (pid);
513  return;
514 }
515 
516 void
518 {
519  NS_LOG_FUNCTION (this);
520  PollTable *table = new PollTable ();
521  table->SetEventMask (POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDHUP);
522  PollTable *pwait = table;
523 
524  // Infinite loop
525  while (true)
526  {
527  uint16_t pid = EnterFakeTask ();
528  int mask = this->m_kernsock->Poll (pwait);
529  if (mask < 0)
530  {
531  NS_LOG_INFO ("poll returns " << mask << " errno " << Current ()->err);
532  continue;
533  }
534  LeaveFakeTask (pid);
535 
536  // Notify the data
537  mask &= (POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDHUP);
538  if (mask)
539  {
540  Ptr<LinuxSocketFdFactory> factory = 0;
541  Ptr<Node> node = GetNode ();
542  Ptr<DceManager> manager = node->GetObject<DceManager> ();
543  factory = manager->GetObject<LinuxSocketFdFactory> ();
544  if (m_listening)
545  {
546  struct sockaddr_storage my_addr;
547  socklen_t addrlen = sizeof (struct sockaddr_storage);
548  Address fromAddress;
549 
550  NS_LOG_INFO ("notify accept");
551  Ptr<LinuxSocketImpl> newSock = CreateObject<LinuxSocketImpl> ();
552  newSock->SetNode (m_node);
553  newSock->m_family = m_family;
554  newSock->m_socktype = m_socktype;
555  newSock->m_protocol = m_protocol;
556 
557  pid = EnterFakeTask ();
558  int sock = this->m_kernsock->Accept ((struct sockaddr *)&my_addr, &addrlen);
559  if (sock < 0)
560  {
561  NS_LOG_INFO ("accept error");
562  }
563  LinuxSocketFd *kern_sock;
564  FileUsage *fu = Current ()->process->openFiles[sock];
565  kern_sock = (LinuxSocketFd *)fu->GetFileInc ();
566  kern_sock->IncFdCount ();
567  kern_sock->Fcntl (F_SETFL, O_NONBLOCK);
568 
569  newSock->m_kernsock = kern_sock;
570  newSock->m_listening = false;
571  fromAddress = m_posixtons3 ((struct sockaddr *)&my_addr, addrlen);
572  LeaveFakeTask (pid);
573  NotifyNewConnectionCreated (newSock, fromAddress);
574  Simulator::ScheduleWithContext (m_node->GetId (), Seconds (0.0),
576  MakeEvent (&LinuxSocketImpl::Poll, newSock));
577  }
578  else if (m_conn_inprogress)
579  {
580  NS_LOG_INFO ("notify conn inprogress finish");
581  NotifyConnectionSucceeded ();
582  m_conn_inprogress = false;
583 
584  NS_LOG_FUNCTION ("CALL>> Wait mask (after conn) " << mask);
585  table->Wait (Seconds (0));
586  NS_LOG_FUNCTION ("RTRN<< Wait mask (after conn) " << mask);
587  }
588  else
589  {
590  // FIXME: handle closed socket
591  if (mask & POLLRDHUP || mask & POLLHUP)
592  {
593  NS_LOG_FUNCTION ("socket has closed ?" << mask);
594  // FIXME: may need m_closed flag
595  // Close ();
596  // XXX:::...
597  Current ()->process->manager->Wait ();
598  }
599 
600  else if (mask & POLLIN || mask & POLLERR)
601  {
602  NS_LOG_INFO ("notify recv");
603  NotifyDataRecv ();
604  }
605  else if (mask & POLLOUT)
606  {
607  Simulator::ScheduleWithContext (m_node->GetId (), Seconds (0.0),
608  MakeEvent (&LinuxSocketImpl::NotifySend, this, 0));
609  NS_LOG_INFO ("wait send for next poll event");
610  table->Wait (Seconds (0));
611  NS_LOG_INFO ("awaken");
612  }
613  }
614  }
615  // if not masked
616  else
617  {
618  NS_LOG_INFO ("wait for next poll event");
619  table->Wait (Seconds (0));
620  NS_LOG_INFO ("awaken");
621  }
622 
623  // next loop
624  pwait = NULL;
625  }
626 }
627 
628 void
629 LinuxSocketImpl::SetNode (Ptr<Node> node)
630 {
631  NS_LOG_FUNCTION_NOARGS ();
632  m_node = node;
633  return;
634 }
635 
636 Ptr<Node>
638 {
639  return m_node;
640 }
641 
642 void
644 {
645  NS_LOG_FUNCTION_NOARGS ();
646  m_ns3toposix = cb;
647  return;
648 }
649 
650 void
652 {
653  NS_LOG_FUNCTION_NOARGS ();
654  m_posixtons3 = cb;
655  return;
656 }
657 
658 void
660 {
661  NS_LOG_FUNCTION_NOARGS ();
662  uint16_t pid = EnterFakeTask ();
663  Ptr<LinuxSocketFdFactory> factory = m_node->GetObject<LinuxSocketFdFactory> ();
664  LinuxSocketFd *kern_sock = (LinuxSocketFd *)
665  factory->CreateSocket (m_family, m_socktype, m_protocol);
666  LeaveFakeTask (pid);
667  if (kern_sock < 0)
668  {
669  NS_ASSERT (0);
670  return;
671  }
672  kern_sock->Fcntl (F_SETFL, O_NONBLOCK);
673  this->m_kernsock = kern_sock;
674 
675  // Poll to register recv callback
676  Simulator::ScheduleWithContext (m_node->GetId (), Seconds (0.0),
678  MakeEvent (&LinuxSocketImpl::Poll, this));
679  return;
680 }
681 
682 void
684 {
685 }
686 
687 uint32_t
689 {
690  return -1;
691 }
692 
693 void
695 {
696 }
697 
698 uint8_t
700 {
701  return -1;
702 }
703 
704 void
706 {
707 }
708 
709 uint8_t
711 {
712  return -1;
713 }
714 
715 void
717 {
718 }
719 
720 int32_t
722 {
723  return -1;
724 }
725 
726 void
728 {
729 }
730 
731 bool
733 {
734  return false;
735 }
736 
737 void
739 {
740  // XXX
741 }
742 bool
744 {
745  return false;
746 }
747 
748 bool
750 {
751  return false;
752 }
753 
754 bool
756 {
757  return false;
758 }
759 
760 
761 } // namespace ns3