ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
linux-socket-fd-factory.cc
Go to the documentation of this file.
2 #include "linux-socket-fd.h"
3 #include "loader-factory.h"
4 #include "dce-manager.h"
5 #include "process.h"
6 #include "utils.h"
7 #include "wait-queue.h"
8 #include "task-manager.h"
9 #include "kingsley-alloc.h"
10 #include "file-usage.h"
11 #include "dce-unistd.h"
12 #include "dce-stdlib.h"
13 #include "sys/dce-stat.h"
14 #include "dce-fcntl.h"
15 #include "dce-stdio.h"
16 #include "sim/include/sim-init.h"
17 #include "ns3/log.h"
18 #include "ns3/string.h"
19 #include "ns3/double.h"
20 #include "ns3/node.h"
21 #include "ns3/net-device.h"
22 #include "ns3/random-variable.h"
23 #include "ns3/event-id.h"
24 #include "ns3/simulator.h"
25 #include "ns3/mac48-address.h"
26 #include "ns3/packet.h"
27 #include "exec-utils.h"
28 #include <dlfcn.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <arpa/inet.h>
34 #include <fcntl.h>
35 
36 NS_LOG_COMPONENT_DEFINE ("LinuxSocketFdFactory");
37 
38 namespace ns3 {
39 
40 // Sadly NetDevice Callback add by method AddLinkChangeCallback take no parameters ..
41 // .. so we need to create the following class to link NetDevice and LinuxSocketFdFactory together
42 // in order to do Warn the factory about which NetDevice is changing .
43 class LinuxDeviceStateListener : public SimpleRefCount<LinuxDeviceStateListener>
44 {
45 public:
46  LinuxDeviceStateListener (Ptr<NetDevice>, Ptr<LinuxSocketFdFactory>);
47 
49 
50 private:
51  Ptr<NetDevice> m_netDevice;
52  Ptr<LinuxSocketFdFactory> m_factory;
53 };
54 
56  Ptr<LinuxSocketFdFactory> f)
57  : m_netDevice (d),
58  m_factory (f)
59 {
60 }
61 
62 void
64 {
65  m_factory->NotifyDeviceStateChange (m_netDevice);
66 }
67 
69 
70 TypeId
72 {
73  static TypeId tid = TypeId ("ns3::LinuxSocketFdFactory")
74  .SetParent<SocketFdFactory> ()
75  .AddConstructor<LinuxSocketFdFactory> ()
76  .AddAttribute ("Library", "File to load in memory",
77  StringValue ("liblinux.so"),
78  MakeStringAccessor (&LinuxSocketFdFactory::m_library),
79  MakeStringChecker ())
80  .AddAttribute ("ErrorRate", "The error rate of malloc().",
81  DoubleValue (DoubleValue (0.0)),
82  MakeDoubleAccessor (&LinuxSocketFdFactory::m_rate),
83  MakeDoubleChecker<double> ())
84  .AddAttribute ("RanVar", "The decision variable attached to this error model.",
85  RandomVariableValue (UniformVariable (0.0, 1.0)),
86  MakeRandomVariableAccessor (&LinuxSocketFdFactory::m_ranvar),
87  MakeRandomVariableChecker ())
88  ;
89  return tid;
90 }
92  : m_loader (0),
93  m_exported (0),
94  m_alloc (new KingsleyAlloc ()),
95  m_logFile (0)
96 {
97  TypeId::LookupByNameFailSafe ("ns3::LteUeNetDevice", &m_lteUeTid);
98 }
99 
101 {
102  for (uint32_t i = 0; i < m_devices.size (); i++)
103  {
104  // Note: we don't really destroy devices from here
105  // because calling destroy requires a task context
106  // m_exported->dev_destroy(m_devices[i].second);
107  }
108  delete m_exported;
109  delete m_loader;
110  delete m_alloc;
111  if (m_logFile != 0)
112  {
113  fclose (m_logFile);
114  }
115  m_exported = 0;
116  m_loader = 0;
117  m_alloc = 0;
118  m_logFile = 0;
119 }
120 
121 void
123 {
124  for (std::list<Task *>::const_iterator i = m_kernelTasks.begin (); i != m_kernelTasks.end (); ++i)
125  {
126  m_manager->Stop (*i);
127  }
128  m_kernelTasks.clear ();
129  m_manager = 0;
130  m_listeners.clear ();
131 }
132 
133 int
134 LinuxSocketFdFactory::Vprintf (struct SimKernel *kernel, const char *str, va_list args)
135 {
136  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
137  return vfprintf (self->m_logFile, str, args);
138 }
139 
140 void *
141 LinuxSocketFdFactory::Malloc (struct SimKernel *kernel, unsigned long size)
142 {
143  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
144  if (self->m_ranvar.GetValue () < self->m_rate)
145  {
146  NS_LOG_DEBUG ("return null");
147  // Inject fault
148  return NULL;
149  }
150 
151  size += sizeof (size_t);
152  uint8_t *buffer = self->m_alloc->Malloc (size);
153  memcpy (buffer, &size, sizeof (size_t));
154  buffer += sizeof (size_t);
155  return buffer;
156 }
157 void
158 LinuxSocketFdFactory::Free (struct SimKernel *kernel, void *ptr)
159 {
160  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
161  uint8_t *buffer = (uint8_t*)ptr;
162  size_t size;
163  buffer -= sizeof (size_t);
164  memcpy (&size, buffer, sizeof (size_t));
165  self->m_alloc->Free (buffer, size);
166 }
167 void *
168 LinuxSocketFdFactory::Memcpy (struct SimKernel *kernel, void *dst, const void *src, unsigned long size)
169 {
170  return memcpy (dst, src, size);
171 }
172 void *
173 LinuxSocketFdFactory::Memset (struct SimKernel *kernel, void *dst, char value, unsigned long size)
174 {
175  return memset (dst, value, size);
176 }
177 int
178 LinuxSocketFdFactory::AtExit (struct SimKernel *kernel, void (*function)(void))
179 {
180  NS_LOG_FUNCTION (kernel << function);
181  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
182  Ptr<DceManager> manager = self->GetObject<DceManager> ();
183  Process *p = manager->SearchProcess (self->m_pid);
184 
185  // Register process-level atexit store
186  struct AtExitHandler handler;
187  handler.type = AtExitHandler::NORMAL;
188  handler.value.normal = function;
189  p->atExitHandlers.push_back (handler);
190  return 0;
191 }
192 int
193 LinuxSocketFdFactory::Access (struct SimKernel *kernel, const char *pathname, int mode)
194 {
195  return dce_access (pathname, mode);
196 }
197 char*
198 LinuxSocketFdFactory::Getenv (struct SimKernel *kernel, const char *name)
199 {
200  return dce_getenv (name);
201 }
202 int
203 LinuxSocketFdFactory::Mkdir (struct SimKernel *kernel, const char *pathname, mode_t mode)
204 {
205  return dce_mkdir (pathname, mode);
206 }
207 int
208 LinuxSocketFdFactory::Open (struct SimKernel *kernel, const char *pathname, int flags)
209 {
210  return dce_open (pathname, flags, 0666);
211 }
212 int
213 LinuxSocketFdFactory::__Fxstat (struct SimKernel *kernel, int ver, int fd, void *buf)
214 {
215  return dce___fxstat (ver, fd, (struct stat *)buf);
216 }
217 int
218 LinuxSocketFdFactory::Fseek (struct SimKernel *kernel, FILE *stream, long offset, int whence)
219 {
220  return dce_fseek (stream, offset, whence);
221 }
222 void
223 LinuxSocketFdFactory::Setbuf (struct SimKernel *kernel, FILE *stream, char *buf)
224 {
225  return dce_setbuf (stream, buf);
226 }
227 long
228 LinuxSocketFdFactory::Ftell (struct SimKernel *kernel, FILE *stream)
229 {
230  return dce_ftell (stream);
231 }
232 FILE*
233 LinuxSocketFdFactory::FdOpen (struct SimKernel *kernel, int fd, const char *mode)
234 {
235  return dce_fdopen (fd, mode);
236 }
237 size_t
238 LinuxSocketFdFactory::Fread (struct SimKernel *kernel, void *ptr, size_t size, size_t nmemb, FILE *stream)
239 {
240  return dce_fread (ptr, size, nmemb, stream);
241 }
242 size_t
243 LinuxSocketFdFactory::Fwrite (struct SimKernel *kernel, const void *ptr, size_t size, size_t nmemb, FILE *stream)
244 {
245  return dce_fwrite (ptr, size, nmemb, stream);
246 }
247 int
248 LinuxSocketFdFactory::Fclose (struct SimKernel *kernel, FILE *fp)
249 {
250  return dce_fclose (fp);
251 }
252 unsigned long
253 LinuxSocketFdFactory::Random (struct SimKernel *kernel)
254 {
255  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
256  union
257  {
258  uint8_t buffer[sizeof(unsigned long)];
259  unsigned long v;
260  } u;
261  for (uint8_t i = 0; i < sizeof (u.buffer); i++)
262  {
263  u.buffer[i] = self->m_variable.GetInteger (0,255);
264  }
265  return u.v;
266 }
267 void
268 LinuxSocketFdFactory::EventTrampoline (void (*fn)(void *context),
269  void *context, void (*pre_fn)(void),
270  Ptr<EventIdHolder> event)
271 {
273  pre_fn ();
274  fn (context);
276 }
277 void *
278 LinuxSocketFdFactory::EventScheduleNs (struct SimKernel *kernel, __u64 ns, void (*fn)(void *context), void *context,
279  void (*pre_fn)(void))
280 {
281  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
282  Ptr<EventIdHolder> ev = Create<EventIdHolder> ();
283  TaskManager *manager = TaskManager::Current ();
284 
285  ev->id = manager->ScheduleMain (NanoSeconds (ns),
286  MakeEvent (&LinuxSocketFdFactory::EventTrampoline, self, fn, context, pre_fn, ev));
287 
288  return &ev->id;
289 }
290 void
291 LinuxSocketFdFactory::EventCancel (struct SimKernel *kernel, void *ev)
292 {
293  EventId *event = (EventId *)ev;
294  Simulator::Remove (*event);
295 }
296 static __u64 CurrentNs (struct SimKernel *kernel)
297 {
298  return Simulator::Now ().GetNanoSeconds ();
299 }
300 
301 void
303 {
304  NS_LOG_FUNCTION (type << context);
305  Loader *loader = (Loader *)context;
306  switch (type)
307  {
308  case Task::TO:
309  loader->NotifyStartExecute ();
310  break;
311  case Task::FROM:
312  loader->NotifyEndExecute ();
313  break;
314  }
315 }
316 
317 struct SimTask *
318 LinuxSocketFdFactory::TaskStart (struct SimKernel *kernel, void (*callback)(void *), void *context)
319 {
320  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
321  Task *task = self->m_manager->Start (callback, context, 1 << 17);
322  struct SimTask *simTask = self->m_exported->task_create (task, 0);
323  task->SetExtraContext (simTask);
324  task->SetSwitchNotifier (&LinuxSocketFdFactory::TaskSwitch, self->m_loader);
325  self->m_kernelTasks.push_back (task);
326  return (struct SimTask *)task->GetExtraContext ();
327 }
328 struct SimTask *
329 LinuxSocketFdFactory::TaskCurrent (struct SimKernel *kernel)
330 {
331  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
332  TaskManager *manager = TaskManager::Current ();
333  Task *current = manager->CurrentTask ();
334  if (current->GetExtraContext () == 0)
335  {
336  uint32_t pid = 0;
337  struct Thread *thread = (struct Thread *)current->GetContext ();
338  if (thread != 0)
339  {
340  pid = thread->process->pid;
341  }
342  struct SimTask *simTask = self->m_exported->task_create (current, pid);
343  current->SetExtraContext (simTask);
344  }
345  return (struct SimTask *)current->GetExtraContext ();
346 }
347 void
348 LinuxSocketFdFactory::TaskWait (struct SimKernel *kernel)
349 {
350  // force initialization of 'current'
351  TaskCurrent (kernel);
352  // now, sleep.
353  TaskManager::Current ()->Sleep ();
354 }
355 int
356 LinuxSocketFdFactory::TaskWakeup (struct SimKernel *kernel, struct SimTask *task)
357 {
358  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
359  TaskManager *manager = TaskManager::Current ();
360  if (!manager)
361  {
362  return 1;
363  }
364  Task *other = (Task *)self->m_exported->task_get_private (task);
365  bool isBlocked = other->IsBlocked ();
366  manager->Wakeup (other);
367  return isBlocked ? 1 : 0;
368 }
369 void
370 LinuxSocketFdFactory::TaskYield (struct SimKernel *kernel)
371 {
372  // force initialization of 'current'
373  TaskCurrent (kernel);
374  // now, yield.
375  TaskManager::Current ()->Yield ();
376 }
377 void
378 LinuxSocketFdFactory::SendMain (bool *r, NetDevice *dev, Ptr<Packet> p, const Address& d, uint16_t pro)
379 {
380  *r = dev->Send (p, d, pro);
381 }
382 void
383 LinuxSocketFdFactory::DevXmit (struct SimKernel *kernel, struct SimDevice *dev, unsigned char *data, int len)
384 {
385  LinuxSocketFdFactory *self = (LinuxSocketFdFactory *)kernel;
386  NetDevice *nsDev = (NetDevice *)self->m_exported->dev_get_private (dev);
387  NS_ASSERT (len >= 14);
388 
389  struct ethhdr
390  {
391  unsigned char h_dest[6];
392  unsigned char h_source[6];
393  uint16_t h_proto;
394  } *hdr = (struct ethhdr *)data;
395  data += 14;
396  len -= 14;
397  Ptr<Packet> p = Create<Packet> (data, len);
398  uint16_t protocol = ntohs (hdr->h_proto);
399  Mac48Address dest;
400  dest.CopyFrom (hdr->h_dest);
401  TaskManager *manager = TaskManager::Current ();
402  bool r = false;
403 
404  manager->ExecOnMain (MakeEvent (&LinuxSocketFdFactory::SendMain, &r, nsDev, p, dest, protocol));
405 }
406 
407 void
408 LinuxSocketFdFactory::SignalRaised (struct SimKernel *kernel, struct SimTask *task, int signalNumber)
409 {
410  NS_LOG_FUNCTION ("XXX: Not Yet Implemented " << signalNumber);
411 }
412 
413 struct SimDevice *
414 LinuxSocketFdFactory::DevToDev (Ptr<NetDevice> device)
415 {
416  for (uint32_t i = 0; i < m_devices.size (); i++)
417  {
418  if (m_devices[i].first == device)
419  {
420  struct SimDevice *dev = m_devices[i].second;
421  return dev;
422  }
423  }
424  return 0;
425 }
426 
427 void
428 LinuxSocketFdFactory::RxFromDevice (Ptr<NetDevice> device, Ptr<const Packet> p,
429  uint16_t protocol, const Address & from,
430  const Address &to, NetDevice::PacketType type)
431 {
432  struct SimDevice *dev = DevToDev (device);
433  if (dev == 0)
434  {
435  return;
436  }
437  m_loader->NotifyStartExecute (); // Restore the memory of the kernel before access it !
438  struct SimDevicePacket packet = m_exported->dev_create_packet (dev, p->GetSize () + 14);
439  p->CopyData (((unsigned char *)packet.buffer) + 14, p->GetSize ());
440  struct ethhdr
441  {
442  unsigned char h_dest[6];
443  unsigned char h_source[6];
444  uint16_t h_proto;
445  } *hdr = (struct ethhdr *)packet.buffer;
446  if (device->GetInstanceTypeId () != m_lteUeTid)
447  {
448  Mac48Address realFrom = Mac48Address::ConvertFrom (from);
449  realFrom.CopyTo (hdr->h_source);
450  }
451  Mac48Address realTo = Mac48Address::ConvertFrom (to);
452  realTo.CopyTo (hdr->h_dest);
453  hdr->h_proto = ntohs (protocol);
454  m_exported->dev_rx (dev, packet);
456 }
457 
458 void
460 {
462  this, device));
463 }
464 void
466 {
467  NS_LOG_FUNCTION (device);
468  struct SimDevice *dev = DevToDev (device);
469  if (dev == 0)
470  {
471  return;
472  }
473  Mac48Address ad = Mac48Address::ConvertFrom (device->GetAddress ());
474  uint8_t buffer[6];
475  ad.CopyTo (buffer);
476  m_loader->NotifyStartExecute (); // Restore the memory of the kernel before access it !
477  m_exported->dev_set_address (dev, buffer);
478  m_exported->dev_set_mtu (dev, device->GetMtu ());
480 }
481 
482 void
484 {
485  Task *current = TaskManager::Current ()->CurrentTask ();
487  current->SetExtraContext (0);
488  EventImpl *event = (EventImpl *)context;
489  event->Invoke ();
490  event->Unref ();
491  self->m_kernelTasks.remove (current);
492  TaskManager::Current ()->Exit ();
493 }
494 
495 void
497 {
499  event, 1 << 17);
500  task->SetExtraContext (this);
502  m_kernelTasks.push_back (task);
503 }
504 
505 void
507 {
508  ScheduleTask (MakeEvent (&LinuxSocketFdFactory::NotifyAddDeviceTask, this, device));
509 }
510 void
512 {
513  NS_LOG_FUNCTION (device);
514  int flags = 0;
515  //NS_ASSERT (!device->IsPointToPoint ());
516  //NS_ASSERT (device->NeedsArp ());
517  //NS_ASSERT (device->IsMulticast ());
518  //NS_ASSERT (device->IsBroadcast ());
519  if (device->IsMulticast ())
520  {
521  flags |= SIM_DEV_MULTICAST;
522  }
523  if (device->IsBroadcast ())
524  {
525  flags |= SIM_DEV_BROADCAST;
526  }
527  if (!device->NeedsArp ())
528  {
529  flags |= SIM_DEV_NOARP;
530  }
531  m_loader->NotifyStartExecute (); // Restore the memory of the kernel before access it !
532  struct SimDevice *dev = m_exported->dev_create (PeekPointer (device), (enum SimDevFlags)flags);
534  Ptr<LinuxDeviceStateListener> listener = Create <LinuxDeviceStateListener> (device, this);
535  m_listeners.push_back (listener);
536  device->AddLinkChangeCallback (MakeCallback (&LinuxDeviceStateListener::NotifyDeviceStateChange, listener));
537 
538  m_devices.push_back (std::make_pair (device,dev));
539  Ptr<Node> node = GetObject<Node> ();
540  if (device->GetInstanceTypeId () == m_lteUeTid)
541  {
542  node->RegisterProtocolHandler (MakeCallback (&LinuxSocketFdFactory::RxFromDevice, this),
543  0, device, false);
544  }
545  else
546  {
547  node->RegisterProtocolHandler (MakeCallback (&LinuxSocketFdFactory::RxFromDevice, this),
548  0, device, true);
549  }
551 }
552 
553 std::vector<std::pair<std::string,struct SimSysFile *> >
555 {
556  struct MyIterator
557  {
558  struct SimSysIterator head;
559  static void ReportStartDir (const struct SimSysIterator *iter, const char *dirname)
560  {
561  struct MyIterator *self = (struct MyIterator *)iter;
562  self->m_stack.push_back (self->m_currentPath);
563  self->m_currentPath += "." + std::string (dirname);
564  }
565  static void ReportEndDir (const struct SimSysIterator *iter)
566  {
567  struct MyIterator *self = (struct MyIterator *)iter;
568  self->m_currentPath = self->m_stack.back ();
569  self->m_stack.pop_back ();
570  }
571  static void ReportFile (const struct SimSysIterator *iter, const char *filename, int flags, struct SimSysFile *file)
572  {
573  struct MyIterator *self = (struct MyIterator *)iter;
574  std::string path = self->m_currentPath + "." + filename;
575  self->m_list.push_back (std::make_pair (path, file));
576  }
577  std::vector<std::string> m_stack;
578  std::vector<std::pair<std::string,struct SimSysFile *> > m_list;
579  std::string m_currentPath;
580  } iter;
581  iter.head.report_start_dir = &MyIterator::ReportStartDir;
582  iter.head.report_end_dir = &MyIterator::ReportEndDir;
583  iter.head.report_file = &MyIterator::ReportFile;
585  m_exported->sys_iterate_files ((struct SimSysIterator *)&iter);
587  return iter.m_list;
588 }
589 
590 void
591 LinuxSocketFdFactory::SetTask (std::string path, std::string value)
592 {
593  NS_LOG_FUNCTION (path << value);
594  std::vector<std::pair<std::string,struct SimSysFile *> > files = GetSysFileList ();
595  for (uint32_t i = 0; i < files.size (); i++)
596  {
597  if (files[i].first == path)
598  {
599  const char *s = value.c_str ();
600  int toWrite = value.size ();
601  int written;
602  written = m_exported->sys_file_write (files[i].second, s, toWrite, 0);
603  break;
604  }
605  }
606 }
607 
608 void
609 LinuxSocketFdFactory::Set (std::string path, std::string value)
610 {
611  if (m_manager == 0)
612  {
613  m_earlySysfs.push_back (std::make_pair (path,value));
614  }
615  else
616  {
617  ScheduleTask (MakeEvent (&LinuxSocketFdFactory::SetTask, this, path, value));
618  }
619 }
620 
621 std::string
622 LinuxSocketFdFactory::Get (std::string path)
623 {
624  NS_LOG_FUNCTION (path);
625  std::string ret;
626  std::vector<std::pair<std::string,struct SimSysFile *> > files = GetSysFileList ();
627  for (uint32_t i = 0; i < files.size (); i++)
628  {
629  if (files[i].first == path)
630  {
631  char buffer[512];
632  memset (buffer, 0, sizeof(buffer));
633  m_exported->sys_file_read (files[i].second, buffer, sizeof(buffer), 0);
634  NS_LOG_FUNCTION ("sysctl read: " << buffer);
635  ret = std::string (buffer);
636  break;
637  }
638  }
639  return ret;
640 }
641 
642 
643 void
645 {
646  std::string filePath = SearchExecFile ("DCE_PATH", m_library, 0);
647  if (filePath.length () <= 0)
648  {
649  std::string line = "Stack file '";
650  line += m_library;
651  line += "' not found ! Please check your DCE_PATH environment variable.";
652  NS_ASSERT_MSG (filePath.length () > 0, line.c_str ());
653  return ;
654  }
655  void *handle = m_loader->Load (filePath, RTLD_LOCAL);
656  void *symbol = m_loader->Lookup (handle, "sim_init");
657  SimInit init = (SimInit) symbol;
658  if (init == 0)
659  {
660  NS_FATAL_ERROR ("Oops. Can't find initialization function");
661  }
662  m_exported = new struct SimExported ();
663  struct SimImported imported;
664  imported.vprintf = &LinuxSocketFdFactory::Vprintf;
665  imported.malloc = &LinuxSocketFdFactory::Malloc;
666  imported.free = &LinuxSocketFdFactory::Free;
667  imported.memcpy = &LinuxSocketFdFactory::Memcpy;
668  imported.memset = &LinuxSocketFdFactory::Memset;
669  imported.atexit = &LinuxSocketFdFactory::AtExit;
670  imported.access = &LinuxSocketFdFactory::Access;
671  imported.getenv = &LinuxSocketFdFactory::Getenv;
672  imported.mkdir = &LinuxSocketFdFactory::Mkdir;
673  imported.open = &LinuxSocketFdFactory::Open;
674  imported.__fxstat = &LinuxSocketFdFactory::__Fxstat;
675  imported.fseek = &LinuxSocketFdFactory::Fseek;
676  imported.setbuf = &LinuxSocketFdFactory::Setbuf;
677  imported.ftell = &LinuxSocketFdFactory::Ftell;
678  imported.fdopen = &LinuxSocketFdFactory::FdOpen;
679  imported.fread = &LinuxSocketFdFactory::Fread;
680  imported.fwrite = &LinuxSocketFdFactory::Fwrite;
681  imported.fclose = &LinuxSocketFdFactory::Fclose;
682  imported.random = &LinuxSocketFdFactory::Random;
683  imported.event_schedule_ns = &LinuxSocketFdFactory::EventScheduleNs;
684  imported.event_cancel = &LinuxSocketFdFactory::EventCancel;
685  imported.current_ns = &CurrentNs;
686  imported.task_start = &LinuxSocketFdFactory::TaskStart;
687  imported.task_wait = &LinuxSocketFdFactory::TaskWait;
688  imported.task_current = &LinuxSocketFdFactory::TaskCurrent;
689  imported.task_wakeup = &LinuxSocketFdFactory::TaskWakeup;
690  imported.task_yield = &LinuxSocketFdFactory::TaskYield;
691  imported.dev_xmit = &LinuxSocketFdFactory::DevXmit;
692  imported.signal_raised = &LinuxSocketFdFactory::SignalRaised;
693  imported.poll_event = &LinuxSocketFdFactory::PollEvent;
694  // create internal process
695  Ptr<DceManager> manager = this->GetObject<DceManager> ();
696  m_pid = manager->StartInternalTask ();
697 
698  init (m_exported, &imported, (struct SimKernel *)this);
699 
700  // update the linux device list with simulation device list
701  Ptr<Node> node = GetObject<Node> ();
702  node->RegisterDeviceAdditionListener (MakeCallback (&LinuxSocketFdFactory::NotifyAddDevice,
703  this));
704  Set (".net.ipv4.conf.all.forwarding", "1");
705  Set (".net.ipv4.conf.all.log_martians", "1");
706  Set (".net.ipv6.conf.all.forwarding", "0");
707 
708  while (!m_earlySysfs.empty ())
709  {
710  std::pair<std::string,std::string> op = m_earlySysfs.front ();
711  Set (op.first, op.second);
712  m_earlySysfs.pop_front ();
713  }
714  NS_LOG_FUNCTION (this << "m_exported " << m_exported);
715 }
716 
717 void
719 {
720  Ptr<Node> node = this->GetObject<Node> ();
721  Ptr<LoaderFactory> loaderFactory = this->GetObject<LoaderFactory> ();
722  Ptr<TaskManager> taskManager = this->GetObject<TaskManager> ();
723  if (node != 0 && loaderFactory != 0 && taskManager != 0 && m_loader == 0)
724  {
725  m_manager = taskManager;
726  m_loader = loaderFactory->Create (0, 0, 0);
727  UtilsEnsureDirectoryExists (UtilsGetAbsRealFilePath (node->GetId (), "/var"));
728  UtilsEnsureDirectoryExists (UtilsGetAbsRealFilePath (node->GetId (), "/var/log"));
729  std::string path = UtilsGetAbsRealFilePath (node->GetId (), "/var/log/messages");
730  m_logFile = fopen (path.c_str (), "w");
731  setlinebuf (m_logFile);
732  // must use ScheduleWithContext to ensure that the initialization task gets
733  // a node context to be able to retrieve the task manager when it runs.
734  // i.e., TaskManager::Current() needs it.
735  Simulator::ScheduleWithContext (node->GetId (), Seconds (0.0),
737  MakeEvent (&LinuxSocketFdFactory::InitializeStack, this));
738  }
739 }
740 
741 UnixFd *
742 LinuxSocketFdFactory::CreateSocket (int domain, int type, int protocol)
743 {
744  GET_CURRENT (this << domain << type << protocol);
745  struct SimSocket *socket;
747  int retval = m_exported->sock_socket (domain, type, protocol, &socket);
749  if (retval < 0)
750  {
751  return 0;
752  }
753  UnixFd *fd = new LinuxSocketFd (this, socket);
754  return fd;
755 }
756 
757 int
758 LinuxSocketFdFactory::Close (struct SimSocket *socket)
759 {
760  GET_CURRENT (socket);
762  int retval = m_exported->sock_close (socket);
764  if (retval < 0)
765  {
766  current->err = -retval;
767  return -1;
768  }
769  return retval;
770 }
771 ssize_t
772 LinuxSocketFdFactory::Recvmsg (struct SimSocket *socket, struct msghdr *msg, int flags)
773 {
774  GET_CURRENT (socket << msg << flags);
776  ssize_t retval = m_exported->sock_recvmsg (socket, msg, flags);
778  if (retval < 0)
779  {
780  current->err = -retval;
781  return -1;
782  }
783  return retval;
784 }
785 ssize_t
786 LinuxSocketFdFactory::Sendmsg (struct SimSocket *socket, const struct msghdr *msg, int flags)
787 {
788  GET_CURRENT (socket << msg << flags);
790  ssize_t retval = m_exported->sock_sendmsg (socket, msg, flags);
792  if (retval < 0)
793  {
794  current->err = -retval;
795  return -1;
796  }
797  return retval;
798 }
799 int
800 LinuxSocketFdFactory::Getsockname (struct SimSocket *socket, struct sockaddr *name, socklen_t *namelen)
801 {
802  GET_CURRENT (socket << name << namelen);
804  int retval = m_exported->sock_getsockname (socket, name, (int*)namelen);
806  if (retval < 0)
807  {
808  current->err = -retval;
809  return -1;
810  }
811  return retval;
812 }
813 int
814 LinuxSocketFdFactory::Getpeername (struct SimSocket *socket, struct sockaddr *name, socklen_t *namelen)
815 {
816  GET_CURRENT (socket << name << namelen);
818  int retval = m_exported->sock_getpeername (socket, name, (int*)namelen);
820  if (retval < 0)
821  {
822  current->err = -retval;
823  return -1;
824  }
825  return retval;
826 }
827 int
828 LinuxSocketFdFactory::Bind (struct SimSocket *socket, const struct sockaddr *my_addr, socklen_t addrlen)
829 {
830  GET_CURRENT (socket << my_addr << addrlen);
832  int retval = m_exported->sock_bind (socket, my_addr, addrlen);
834  if (retval < 0)
835  {
836  current->err = -retval;
837  return -1;
838  }
839  return retval;
840 }
841 int
842 LinuxSocketFdFactory::Connect (struct SimSocket *socket, const struct sockaddr *my_addr,
843  socklen_t addrlen, int flags)
844 {
845  GET_CURRENT (socket << my_addr << addrlen << flags);
847  int retval = m_exported->sock_connect (socket, my_addr, addrlen, flags);
849  if (retval < 0)
850  {
851  current->err = -retval;
852  return -1;
853  }
854  return retval;
855 }
856 int
857 LinuxSocketFdFactory::Listen (struct SimSocket *socket, int backlog)
858 {
859  GET_CURRENT (socket << backlog);
861  int retval = m_exported->sock_listen (socket, backlog);
863  if (retval < 0)
864  {
865  current->err = -retval;
866  return -1;
867  }
868  return retval;
869 }
870 int
871 LinuxSocketFdFactory::Shutdown (struct SimSocket *socket, int how)
872 {
873  GET_CURRENT (socket << how);
875  int retval = m_exported->sock_shutdown (socket, how);
877  if (retval < 0)
878  {
879  current->err = -retval;
880  return -1;
881  }
882  return retval;
883 }
884 int
885 LinuxSocketFdFactory::Accept (struct SimSocket *socket, struct sockaddr *my_addr, socklen_t *addrlen)
886 {
887  GET_CURRENT (socket << my_addr << addrlen);
888  struct SimSocket *newSocket;
889  // XXX: handle O_NONBLOCK
891  int retval = m_exported->sock_accept (socket, &newSocket, 0);
893  if (retval < 0)
894  {
895  current->err = -retval;
896  return -1;
897  }
898  if (my_addr != 0)
899  {
901  retval = m_exported->sock_getpeername (newSocket, my_addr, (int*)addrlen);
902  if (retval < 0)
903  {
904  current->err = -retval;
905  m_exported->sock_close (newSocket);
907  return -1;
908  }
910  }
911  int fd = UtilsAllocateFd ();
912  if (fd == -1)
913  {
915  m_exported->sock_close (newSocket);
916  current->err = EMFILE;
918  return -1;
919  }
920 
921  UnixFd *unixFd = new LinuxSocketFd (this, newSocket);
922  unixFd->IncFdCount ();
923  current->process->openFiles[fd] = new FileUsage (fd, unixFd);
924 
925  return fd;
926 }
927 int
928 LinuxSocketFdFactory::Ioctl (struct SimSocket *socket, int request, char *argp)
929 {
930  GET_CURRENT (socket << request << argp);
932  int retval = m_exported->sock_ioctl (socket, request, argp);
934  if (retval < 0)
935  {
936  current->err = -retval;
937  return -1;
938  }
939  return retval;
940 }
941 int
942 LinuxSocketFdFactory::Setsockopt (struct SimSocket *socket, int level, int optname,
943  const void *optval, socklen_t optlen)
944 {
945  GET_CURRENT (socket << level << optname << optval << optlen);
947  int retval = m_exported->sock_setsockopt (socket, level, optname, optval, optlen);
949  if (retval < 0)
950  {
951  current->err = -retval;
952  return -1;
953  }
954  return retval;
955 }
956 int
957 LinuxSocketFdFactory::Getsockopt (struct SimSocket *socket, int level, int optname,
958  void *optval, socklen_t *optlen)
959 {
960  GET_CURRENT (socket << level << optname << optval << optlen);
962  int retval = m_exported->sock_getsockopt (socket, level, optname, optval, (int*)optlen);
964  if (retval < 0)
965  {
966  current->err = -retval;
967  return -1;
968  }
969  return retval;
970 }
971 void
972 LinuxSocketFdFactory::PollEvent (int flag, void *context)
973 {
974  PollTable* ptable = (PollTable*)context;
975  ptable->WakeUpCallback ();
976 }
977 
994 {
995  int ret;
996  void *opaque;
997 };
998 int
999 LinuxSocketFdFactory::Poll (struct SimSocket *socket, PollTable* ptable)
1000 {
1001  struct poll_table_ref kernelInOut =
1002  {
1003  0
1004  };
1005  if (ptable)
1006  {
1007  // Fill Opaque and ptable.
1008  kernelInOut.opaque = ptable;
1009  kernelInOut.ret = ptable->GetEventMask ();
1010  }
1011 
1012  GET_CURRENT (socket);
1014  m_exported->sock_poll (socket, &kernelInOut);
1016 
1017  if (ptable)
1018  {
1019  ptable->PollWait (kernelInOut.opaque, MakeCallback (&LinuxSocketFdFactory::PollFreeWait, this));
1020  }
1021 
1022  return kernelInOut.ret;
1023 }
1024 void
1026 {
1028  m_exported->sock_pollfreewait (ref);
1030 }
1031 } // namespace ns3