merge in tap device
authorCraig Dowell <craigdo@ee.washington.edu>
Mon Oct 27 13:01:28 2008 -0700 (15 months ago)
changeset 382640c5841b616d
parent 3817 4ed410f69d36
child 3827 4b603cd4ee42
merge in tap device
src/devices/emutap/host-tap-net-device.cc
src/devices/emutap/host-tap-net-device.h
src/devices/emutap/tap-channel.cc
src/devices/emutap/tap-channel.h
src/devices/emutap/tap-manager-client.cc
src/devices/emutap/tap-manager-client.h
src/devices/emutap/tap-manager.cc
src/devices/emutap/tap-net-device.cc
src/devices/emutap/tap-net-device.h
src/devices/emutap/wscript
src/wscript
wscript
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/devices/emutap/host-tap-net-device.cc	Mon Oct 27 13:01:28 2008 -0700
     1.3 @@ -0,0 +1,194 @@
     1.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     1.5 +/*
     1.6 + * Copyright (c) 2008 INRIA
     1.7 + *
     1.8 + * This program is free software; you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License version 2 as
    1.10 + * published by the Free Software Foundation;
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program; if not, write to the Free Software
    1.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.20 + *
    1.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    1.22 + */
    1.23 +#include "host-tap-net-device.h"
    1.24 +#include "ns3/node.h"
    1.25 +#include "ns3/tap-channel.h"
    1.26 +#include "ns3/log.h"
    1.27 +
    1.28 +NS_LOG_COMPONENT_DEFINE ("HostTapNetDevice");
    1.29 +
    1.30 +namespace ns3 {
    1.31 +
    1.32 +TypeId 
    1.33 +HostTapNetDevice::GetTypeId (void)
    1.34 +{
    1.35 +  static TypeId tid = TypeId ("ns3::HostTapNetDevice")
    1.36 +    .SetParent<NetDevice> ()
    1.37 +    .AddConstructor<HostTapNetDevice> ()
    1.38 +    ;
    1.39 +  return tid;
    1.40 +}
    1.41 +
    1.42 +HostTapNetDevice::HostTapNetDevice ()
    1.43 +  : m_node (0),
    1.44 +    m_mtu (0xffff),
    1.45 +    m_name (""),
    1.46 +    m_ifIndex (0)
    1.47 +{
    1.48 +  NS_LOG_FUNCTION (this);
    1.49 +}
    1.50 +
    1.51 +void 
    1.52 +HostTapNetDevice::SetChannel (Ptr<TapChannel> channel)
    1.53 +{
    1.54 +  m_channel = channel;
    1.55 +  m_channel->SetHostDevice (this);
    1.56 +}
    1.57 +
    1.58 +void 
    1.59 +HostTapNetDevice::SetAddress (Mac48Address address)
    1.60 +{
    1.61 +  m_address = address;
    1.62 +}
    1.63 +
    1.64 +Mac48Address 
    1.65 +HostTapNetDevice::GetMacAddress (void) const
    1.66 +{
    1.67 +  return m_address;
    1.68 +}
    1.69 +
    1.70 +void 
    1.71 +HostTapNetDevice::SetName(const std::string name)
    1.72 +{
    1.73 +  m_name = name;
    1.74 +}
    1.75 +std::string 
    1.76 +HostTapNetDevice::GetName(void) const
    1.77 +{
    1.78 +  return m_name;
    1.79 +}
    1.80 +void 
    1.81 +HostTapNetDevice::SetIfIndex(const uint32_t index)
    1.82 +{
    1.83 +  m_ifIndex = index;
    1.84 +}
    1.85 +uint32_t 
    1.86 +HostTapNetDevice::GetIfIndex(void) const
    1.87 +{
    1.88 +  return m_ifIndex;
    1.89 +}
    1.90 +Ptr<Channel> 
    1.91 +HostTapNetDevice::GetChannel (void) const
    1.92 +{
    1.93 +  return m_channel;
    1.94 +}
    1.95 +Address 
    1.96 +HostTapNetDevice::GetAddress (void) const
    1.97 +{
    1.98 +  return m_address;
    1.99 +}
   1.100 +bool 
   1.101 +HostTapNetDevice::SetMtu (const uint16_t mtu)
   1.102 +{
   1.103 +  m_mtu = mtu;
   1.104 +  return true;
   1.105 +}
   1.106 +uint16_t 
   1.107 +HostTapNetDevice::GetMtu (void) const
   1.108 +{
   1.109 +  return m_mtu;
   1.110 +}
   1.111 +bool 
   1.112 +HostTapNetDevice::IsLinkUp (void) const
   1.113 +{
   1.114 +  return true;
   1.115 +}
   1.116 +void 
   1.117 +HostTapNetDevice::SetLinkChangeCallback (Callback<void> callback)
   1.118 +{}
   1.119 +bool 
   1.120 +HostTapNetDevice::IsBroadcast (void) const
   1.121 +{
   1.122 +  return true;
   1.123 +}
   1.124 +Address
   1.125 +HostTapNetDevice::GetBroadcast (void) const
   1.126 +{
   1.127 +  return Mac48Address ("ff:ff:ff:ff:ff:ff");
   1.128 +}
   1.129 +bool 
   1.130 +HostTapNetDevice::IsMulticast (void) const
   1.131 +{
   1.132 +  return true;
   1.133 +}
   1.134 +Address 
   1.135 +HostTapNetDevice::GetMulticast (void) const
   1.136 +{
   1.137 +  return Mac48Address::GetMulticastPrefix ();
   1.138 +}
   1.139 +Address 
   1.140 +HostTapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
   1.141 +{
   1.142 +  return Mac48Address::GetMulticast (multicastGroup);
   1.143 +}
   1.144 +bool 
   1.145 +HostTapNetDevice::IsPointToPoint (void) const
   1.146 +{
   1.147 +  return false;
   1.148 +}
   1.149 +bool 
   1.150 +HostTapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
   1.151 +{
   1.152 +  return false;
   1.153 +}
   1.154 +bool 
   1.155 +HostTapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
   1.156 +{
   1.157 +  return false;
   1.158 +}
   1.159 +Ptr<Node> 
   1.160 +HostTapNetDevice::GetNode (void) const
   1.161 +{
   1.162 +  return m_node;
   1.163 +}
   1.164 +void 
   1.165 +HostTapNetDevice::SetNode (Ptr<Node> node)
   1.166 +{
   1.167 +  m_node = node;
   1.168 +}
   1.169 +bool 
   1.170 +HostTapNetDevice::NeedsArp (void) const
   1.171 +{
   1.172 +  return false;
   1.173 +}
   1.174 +void 
   1.175 +HostTapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
   1.176 +{}
   1.177 +
   1.178 +void
   1.179 +HostTapNetDevice::DoDispose (void)
   1.180 +{
   1.181 +  NS_LOG_FUNCTION (this);
   1.182 +  m_node = 0;
   1.183 +  m_channel = 0;
   1.184 +  NetDevice::DoDispose ();
   1.185 +}
   1.186 +
   1.187 +void
   1.188 +HostTapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
   1.189 +{}
   1.190 +
   1.191 +bool
   1.192 +HostTapNetDevice::SupportsSendFrom (void) const
   1.193 +{
   1.194 +  return false;
   1.195 +}
   1.196 +
   1.197 +} // namespace ns3
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/devices/emutap/host-tap-net-device.h	Mon Oct 27 13:01:28 2008 -0700
     2.3 @@ -0,0 +1,90 @@
     2.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2.5 +/*
     2.6 + * Copyright (c) 2008 INRIA
     2.7 + *
     2.8 + * This program is free software; you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License version 2 as
    2.10 + * published by the Free Software Foundation;
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program; if not, write to the Free Software
    2.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.20 + *
    2.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    2.22 + */
    2.23 +#ifndef HOST_TAP_NET_DEVICE_H
    2.24 +#define HOST_TAP_NET_DEVICE_H
    2.25 +
    2.26 +#include "ns3/net-device.h"
    2.27 +#include "ns3/mac48-address.h"
    2.28 +#include "ns3/traced-callback.h"
    2.29 +#include <stdint.h>
    2.30 +#include <string>
    2.31 +
    2.32 +namespace ns3 {
    2.33 +
    2.34 +class Node;
    2.35 +class TapChannel;
    2.36 +
    2.37 +
    2.38 +/**
    2.39 + * \ingroup netdevice
    2.40 + * 
    2.41 + * \brief a NetDevice to get packets to and from a host tap device.
    2.42 + */
    2.43 +class HostTapNetDevice : public NetDevice
    2.44 +{
    2.45 +public:
    2.46 +  static TypeId GetTypeId (void);
    2.47 +  HostTapNetDevice ();
    2.48 +
    2.49 +  void SetAddress (Mac48Address address);
    2.50 +  void SetChannel (Ptr<TapChannel> channel);
    2.51 +
    2.52 +  Mac48Address GetMacAddress (void) const;
    2.53 +
    2.54 +  // inherited from NetDevice base class.
    2.55 +  virtual void SetName(const std::string name);
    2.56 +  virtual std::string GetName(void) const;
    2.57 +  virtual void SetIfIndex(const uint32_t index);
    2.58 +  virtual uint32_t GetIfIndex(void) const;
    2.59 +  virtual Ptr<Channel> GetChannel (void) const;
    2.60 +  virtual Address GetAddress (void) const;
    2.61 +  virtual bool SetMtu (const uint16_t mtu);
    2.62 +  virtual uint16_t GetMtu (void) const;
    2.63 +  virtual bool IsLinkUp (void) const;
    2.64 +  virtual void SetLinkChangeCallback (Callback<void> callback);
    2.65 +  virtual bool IsBroadcast (void) const;
    2.66 +  virtual Address GetBroadcast (void) const;
    2.67 +  virtual bool IsMulticast (void) const;
    2.68 +  virtual Address GetMulticast (void) const;
    2.69 +  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
    2.70 +  virtual bool IsPointToPoint (void) const;
    2.71 +  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
    2.72 +  virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
    2.73 +  virtual Ptr<Node> GetNode (void) const;
    2.74 +  virtual void SetNode (Ptr<Node> node);
    2.75 +  virtual bool NeedsArp (void) const;
    2.76 +  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
    2.77 +  virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
    2.78 +  virtual bool SupportsSendFrom (void) const;
    2.79 +
    2.80 +protected:
    2.81 +  virtual void DoDispose (void);
    2.82 +private:
    2.83 +  Ptr<Node> m_node;
    2.84 +  uint16_t m_mtu;
    2.85 +  std::string m_name;
    2.86 +  uint32_t m_ifIndex;
    2.87 +  Mac48Address m_address;
    2.88 +  Ptr<TapChannel> m_channel;
    2.89 +};
    2.90 +
    2.91 +} // namespace ns3
    2.92 +
    2.93 +#endif /* HOST_TAP_NET_DEVICE_H */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/devices/emutap/tap-channel.cc	Mon Oct 27 13:01:28 2008 -0700
     3.3 @@ -0,0 +1,61 @@
     3.4 +#include "tap-channel.h"
     3.5 +#include "host-tap-net-device.h"
     3.6 +#include "tap-net-device.h"
     3.7 +
     3.8 +namespace ns3 {
     3.9 +
    3.10 +
    3.11 +TapChannel::TapChannel ()
    3.12 +  : m_hostDevice (0),
    3.13 +    m_device (0)
    3.14 +{}
    3.15 +
    3.16 +void
    3.17 +TapChannel::DoDispose (void)
    3.18 +{
    3.19 +  m_device = 0;
    3.20 +  m_hostDevice = 0;
    3.21 +  Channel::DoDispose ();
    3.22 +}
    3.23 +
    3.24 +void
    3.25 +TapChannel::SetDevice (Ptr<TapNetDevice> device)
    3.26 +{
    3.27 +  m_device = device;
    3.28 +}
    3.29 +
    3.30 +void
    3.31 +TapChannel::SetHostDevice (Ptr<HostTapNetDevice> device)
    3.32 +{
    3.33 +  m_hostDevice = device;
    3.34 +}
    3.35 +
    3.36 +Ptr<HostTapNetDevice> 
    3.37 +TapChannel::GetHostDevice (void) const
    3.38 +{
    3.39 +  return m_hostDevice;
    3.40 +}
    3.41 +
    3.42 +uint32_t 
    3.43 +TapChannel::GetNDevices (void) const
    3.44 +{
    3.45 +  return 2;
    3.46 +}
    3.47 +Ptr<NetDevice> 
    3.48 +TapChannel::GetDevice (uint32_t i) const
    3.49 +{
    3.50 +  if (i == 0)
    3.51 +    {
    3.52 +      return m_device;
    3.53 +    }
    3.54 +  else if (i == 1)
    3.55 +    {
    3.56 +      return m_hostDevice;
    3.57 +    }
    3.58 +  else
    3.59 +    {
    3.60 +      return 0;
    3.61 +    }
    3.62 +}
    3.63 +
    3.64 +} // namespace ns3
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/devices/emutap/tap-channel.h	Mon Oct 27 13:01:28 2008 -0700
     4.3 @@ -0,0 +1,36 @@
     4.4 +#ifndef TAP_CHANNEL_H
     4.5 +#define TAP_CHANNEL_H
     4.6 +
     4.7 +#include "ns3/channel.h"
     4.8 +
     4.9 +namespace ns3 {
    4.10 +
    4.11 +class HostTapNetDevice;
    4.12 +class TapNetDevice;
    4.13 +class NetDevice;
    4.14 +
    4.15 +
    4.16 +class TapChannel : public Channel
    4.17 +{
    4.18 +public:
    4.19 +  TapChannel ();
    4.20 +
    4.21 +  void SetHostDevice (Ptr<HostTapNetDevice> device);
    4.22 +  void SetDevice (Ptr<TapNetDevice> device);
    4.23 +
    4.24 +  Ptr<HostTapNetDevice> GetHostDevice (void) const;
    4.25 +
    4.26 +  // overriden from Channel base class
    4.27 +  virtual uint32_t GetNDevices (void) const;
    4.28 +  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
    4.29 +
    4.30 +private:
    4.31 +  virtual void DoDispose (void);
    4.32 +
    4.33 +  Ptr<HostTapNetDevice> m_hostDevice;
    4.34 +  Ptr<TapNetDevice> m_device;
    4.35 +};
    4.36 +
    4.37 +} // namespace ns3
    4.38 +
    4.39 +#endif /* TAP_CHANNEL_H */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/devices/emutap/tap-manager-client.cc	Mon Oct 27 13:01:28 2008 -0700
     5.3 @@ -0,0 +1,180 @@
     5.4 +#include "tap-manager-client.h"
     5.5 +#include "ns3/log.h"
     5.6 +#include <sys/socket.h>
     5.7 +#include <sys/wait.h>
     5.8 +#include <sys/stat.h>
     5.9 +#include <linux/un.h>
    5.10 +#include <errno.h>
    5.11 +#include <string.h>
    5.12 +#include <iomanip>
    5.13 +#include <iostream>
    5.14 +#include <list>
    5.15 +
    5.16 +
    5.17 +NS_LOG_COMPONENT_DEFINE("TapManagerClient");
    5.18 +
    5.19 +#define TAP_MANAGER "ns3-tap-manager"
    5.20 +
    5.21 +namespace ns3 {
    5.22 +
    5.23 +static std::string
    5.24 +EncodeAsString (struct sockaddr_un un, int len)
    5.25 +{
    5.26 +  uint8_t *buffer = (uint8_t *)&un;
    5.27 +  std::ostringstream oss;
    5.28 +  oss.setf (std::ios::hex, std::ios::basefield);
    5.29 +  oss.fill('0');
    5.30 +  for (uint8_t i = 0; i < len; i++)
    5.31 +    {
    5.32 +      oss << ":" << std::setw (2) << (uint32_t)buffer[i];
    5.33 +    }
    5.34 +  return oss.str ();
    5.35 +}
    5.36 +
    5.37 +bool
    5.38 +TapManagerClient::Exists (std::string filename) const
    5.39 +{
    5.40 +  struct stat st;
    5.41 +  int retval = ::stat (filename.c_str (), &st);
    5.42 +  return retval == 0;
    5.43 +}
    5.44 +
    5.45 +std::string
    5.46 +TapManagerClient::FindManager (void) const
    5.47 +{
    5.48 +  std::list<std::string> locations;
    5.49 +  locations.push_back ("./src/devices/tap");
    5.50 +  locations.push_back ("./build/debug/src/devices/tap");
    5.51 +  locations.push_back ("./build/optimized/src/devices/tap");
    5.52 +  for (std::list<std::string>::const_iterator i = locations.begin (); i != locations.end (); ++i)
    5.53 +    {
    5.54 +      if (Exists (*i + "/" + TAP_MANAGER))
    5.55 +	{
    5.56 +	  return *i + "/" + TAP_MANAGER;
    5.57 +	}
    5.58 +    }
    5.59 +  NS_FATAL_ERROR ("Could not find manager");
    5.60 +  return ""; // quiet compiler
    5.61 +}
    5.62 +
    5.63 +int
    5.64 +TapManagerClient::AllocateTap (Mac48Address host, Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
    5.65 +{
    5.66 +  NS_LOG_FUNCTION (host << ad << mask << gateway);
    5.67 +  // create a socket to get information back from the tap manager.
    5.68 +  int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
    5.69 +  if (sock == -1)
    5.70 +    {
    5.71 +      NS_FATAL_ERROR ("Socket creation, errno=" << strerror (errno));
    5.72 +    }
    5.73 +
    5.74 +  struct sockaddr_un un;
    5.75 +  memset (&un, 0, sizeof (un));
    5.76 +  un.sun_family = AF_UNIX;
    5.77 +  int status = bind (sock, (struct sockaddr*)&un, sizeof (sa_family_t)); // let the kernel allocate an endpoint for us.
    5.78 +  if (status == -1)
    5.79 +    {
    5.80 +      NS_FATAL_ERROR ("Could not bind: errno=" << strerror (errno));
    5.81 +    }
    5.82 +  socklen_t len = sizeof (un);
    5.83 +  status = getsockname (sock, (struct sockaddr*)&un, &len);
    5.84 +  if (status == -1)
    5.85 +    {
    5.86 +      NS_FATAL_ERROR ("Could not get socket address: errno=" << strerror (errno));
    5.87 +    }
    5.88 +  NS_LOG_DEBUG ("Allocated enpoint=" << EncodeAsString (un, len) << ", len=" << len);
    5.89 +
    5.90 +  pid_t pid = ::fork ();
    5.91 +  if (pid == 0)
    5.92 +    {
    5.93 +      // child.
    5.94 +      NS_LOG_DEBUG ("Child");
    5.95 +
    5.96 +      std::ostringstream oss;
    5.97 +      oss << "--path=" << EncodeAsString (un, len);
    5.98 +      std::string pathArg = oss.str ();
    5.99 +      oss.str ("");
   5.100 +      oss << "--mac-addr=" << host;
   5.101 +      std::string hostArg = oss.str ();
   5.102 +      oss.str ("");
   5.103 +      oss << "--ip-addr=" << ad;
   5.104 +      std::string ipArg = oss.str ();
   5.105 +      oss.str ("");
   5.106 +      oss << "--ip-gw=" << gateway;
   5.107 +      std::string ipGw = oss.str ();
   5.108 +      oss.str ("");
   5.109 +      oss << "--ip-netmask=" << mask;
   5.110 +      std::string ipMask = oss.str ();
   5.111 +      oss.str ("");
   5.112 +      status = ::execl (FindManager ().c_str (), 
   5.113 +			TAP_MANAGER, 
   5.114 +			pathArg.c_str (),
   5.115 +			hostArg.c_str (),
   5.116 +			ipArg.c_str (),
   5.117 +			ipGw.c_str (),
   5.118 +			ipMask.c_str (),
   5.119 +			(char *)NULL);
   5.120 +      if (status == -1)
   5.121 +	{
   5.122 +	  NS_LOG_ERROR ("Cannot execl tap-manager, errno=" << ::strerror (errno));
   5.123 +	}
   5.124 +      ::_exit (-1);
   5.125 +    }
   5.126 +  else
   5.127 +    {
   5.128 +      // parent
   5.129 +      NS_LOG_DEBUG ("Parent");
   5.130 +      int st;
   5.131 +      pid_t waited = waitpid (pid, &st, 0);
   5.132 +      if (waited == -1)
   5.133 +	{
   5.134 +	  NS_FATAL_ERROR ("Cannot wait for tap-manager, errno=" << strerror (errno));
   5.135 +	}
   5.136 +      NS_ASSERT (pid == waited);
   5.137 +      if (!WIFEXITED (st))
   5.138 +	{
   5.139 +	  // tap manager did not complete successfully
   5.140 +	  NS_FATAL_ERROR ("tap-manager did not exit correctly");
   5.141 +	}
   5.142 +      else if (WEXITSTATUS (st) != 0)
   5.143 +	{
   5.144 +	  NS_FATAL_ERROR ("tap-manager did not complete successfully, err=" << WEXITSTATUS (st));
   5.145 +	}
   5.146 +      // the tap fd should be available on our unix socket now.
   5.147 +      size_t msg_size = sizeof(int);
   5.148 +      char control[CMSG_SPACE(msg_size)];
   5.149 +      struct cmsghdr *cmsg;
   5.150 +      uint8_t buffer;
   5.151 +      struct iovec iov;
   5.152 +      iov.iov_base = &buffer;
   5.153 +      iov.iov_len = 1;
   5.154 +      struct msghdr msg;
   5.155 +      msg.msg_name = 0;
   5.156 +      msg.msg_namelen = 0;
   5.157 +      msg.msg_iov = &iov;
   5.158 +      msg.msg_iovlen = 1;
   5.159 +      msg.msg_control = control;
   5.160 +      msg.msg_controllen = sizeof (control);
   5.161 +      msg.msg_flags = 0;
   5.162 +      ssize_t bytesRead = recvmsg (sock, &msg, 0);
   5.163 +      if (bytesRead != 1)
   5.164 +	{
   5.165 +	  NS_FATAL_ERROR ("Did not get byte from tap-manager");
   5.166 +	}
   5.167 +      NS_LOG_ERROR ("read bytes=" << bytesRead);
   5.168 +      for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) 
   5.169 +	{
   5.170 +	  if (cmsg->cmsg_level == SOL_SOCKET &&
   5.171 +	      cmsg->cmsg_type == SCM_RIGHTS)
   5.172 +	    {
   5.173 +	      int *fd = (int*)CMSG_DATA (cmsg);
   5.174 +	      NS_LOG_ERROR ("got tap fd=" << *fd);
   5.175 +	      return *fd;
   5.176 +	    }
   5.177 +	}
   5.178 +      NS_FATAL_ERROR ("Did not get SCM_RIGHTS from tap-manager");
   5.179 +    }
   5.180 +  return -1;
   5.181 +}
   5.182 +
   5.183 +} // namespace ns3
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/devices/emutap/tap-manager-client.h	Mon Oct 27 13:01:28 2008 -0700
     6.3 @@ -0,0 +1,21 @@
     6.4 +#ifndef TAP_MANAGER_CLIENT_H
     6.5 +#define TAP_MANAGER_CLIENT_H
     6.6 +
     6.7 +#include "ns3/mac48-address.h"
     6.8 +#include "ns3/ipv4-address.h"
     6.9 +#include <string>
    6.10 +
    6.11 +namespace ns3 {
    6.12 +
    6.13 +class TapManagerClient
    6.14 +{
    6.15 +public:
    6.16 +  int AllocateTap (Mac48Address host, Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway);
    6.17 +private:
    6.18 +  std::string FindManager (void) const;
    6.19 +  bool Exists (std::string filename) const;
    6.20 +};
    6.21 +
    6.22 +} // namespace ns3
    6.23 +
    6.24 +#endif /* TAP_MANAGER_CLIENT_H */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/devices/emutap/tap-manager.cc	Mon Oct 27 13:01:28 2008 -0700
     7.3 @@ -0,0 +1,339 @@
     7.4 +#include <fcntl.h>
     7.5 +#include <sys/ioctl.h>
     7.6 +#include <sys/types.h>
     7.7 +#include <sys/socket.h>
     7.8 +#include <linux/un.h>
     7.9 +#include <linux/if.h>
    7.10 +#include <linux/if_tun.h>
    7.11 +#include <linux/route.h>
    7.12 +#include <netinet/in.h>
    7.13 +#include <stdint.h>
    7.14 +#include <iostream>
    7.15 +#include <sstream>
    7.16 +#include <iomanip>
    7.17 +#include <string.h>
    7.18 +#include <errno.h>
    7.19 +#include <stdlib.h>
    7.20 +
    7.21 +#define noENABLE_LOG
    7.22 +
    7.23 +#define EXIT_ERROR(x, err)						\
    7.24 +  std::cout << __FILE__ << ":" << __LINE__ << ": Unrecoverable Error: " << x; \
    7.25 +  std::cout << " errno=" << strerror (errno) << std::endl;		\
    7.26 +  exit (err)
    7.27 +#ifdef ENABLE_LOG
    7.28 +#define LOG(x) \
    7.29 +  std::cout << x << std::endl;
    7.30 +#else
    7.31 +#define LOG(x)
    7.32 +#endif
    7.33 +
    7.34 +
    7.35 +#define CHECK_ARG(el,var) \
    7.36 +  {						\
    7.37 +    char start[] = "--"  el  "=";		     \
    7.38 +    if (strncmp (*argv, start, strlen (start)) == 0) \
    7.39 +      {						     \
    7.40 +	var = *argv + strlen (start);		     \
    7.41 +	LOG ("--" << el << "=" << var);		     \
    7.42 +      }						     \
    7.43 +  }
    7.44 +
    7.45 +#define ASCII_DOT (0x2e)
    7.46 +#define ASCII_ZERO (0x30)
    7.47 +#define ASCII_a (0x41)
    7.48 +#define ASCII_z (0x5a)
    7.49 +#define ASCII_A (0x61)
    7.50 +#define ASCII_Z (0x7a)
    7.51 +#define ASCII_COLON (0x3a)
    7.52 +#define ASCII_ZERO (0x30)
    7.53 +static char
    7.54 +AsciiToLowCase (char c)
    7.55 +{
    7.56 +  if (c >= ASCII_a && c <= ASCII_z) {
    7.57 +    return c;
    7.58 +  } else if (c >= ASCII_A && c <= ASCII_Z) {
    7.59 +    return c + (ASCII_a - ASCII_A);
    7.60 +  } else {
    7.61 +    return c;
    7.62 +  }
    7.63 +}
    7.64 +static uint32_t 
    7.65 +AsciiToIpv4 (const char *address)
    7.66 +{
    7.67 +  uint32_t host = 0;
    7.68 +  while (true) {
    7.69 +    uint8_t byte = 0;
    7.70 +    while (*address != ASCII_DOT &&
    7.71 +           *address != 0) {
    7.72 +      byte *= 10;
    7.73 +      byte += *address - ASCII_ZERO;
    7.74 +      address++;
    7.75 +    }
    7.76 +    host <<= 8;
    7.77 +    host |= byte;
    7.78 +    if (*address == 0) {
    7.79 +      break;
    7.80 +    }
    7.81 +    address++;
    7.82 +  }
    7.83 +  return host;
    7.84 +}
    7.85 +
    7.86 +static void 
    7.87 +AsciiToMac48 (const char *str, uint8_t addr[6])
    7.88 +{
    7.89 +  int i = 0;
    7.90 +  while (*str != 0 && i < 6) 
    7.91 +    {
    7.92 +      uint8_t byte = 0;
    7.93 +      while (*str != ASCII_COLON && *str != 0) 
    7.94 +	{
    7.95 +	  byte <<= 4;
    7.96 +	  char low = AsciiToLowCase (*str);
    7.97 +	  if (low >= ASCII_a) 
    7.98 +	    {
    7.99 +	      byte |= low - ASCII_a + 10;
   7.100 +	    } 
   7.101 +	  else 
   7.102 +	    {
   7.103 +	      byte |= low - ASCII_ZERO;
   7.104 +	    }
   7.105 +	  str++;
   7.106 +	}
   7.107 +      addr[i] = byte;
   7.108 +      i++;
   7.109 +      if (*str == 0) 
   7.110 +	{
   7.111 +	  break;
   7.112 +	}
   7.113 +      str++;
   7.114 +    }
   7.115 +}
   7.116 +
   7.117 +static void
   7.118 +SetInetAddress (sockaddr *ad, uint32_t networkOrder)
   7.119 +{
   7.120 +  struct sockaddr_in *sin = (struct sockaddr_in*)ad;
   7.121 +  sin->sin_family = AF_INET;
   7.122 +  sin->sin_port = 0; // unused
   7.123 +  sin->sin_addr.s_addr = htonl (networkOrder);
   7.124 +}
   7.125 +
   7.126 +
   7.127 +static int
   7.128 +CreateTap (const char *mac_addr, const char *ip, 
   7.129 +	   const char *gw, const char *netmask)
   7.130 +{
   7.131 +  // opening the tun device usually requires root privs
   7.132 +  int tap = open ("/dev/net/tun", O_RDWR);
   7.133 +  if (tap == -1)
   7.134 +    {
   7.135 +      EXIT_ERROR ("Could not open /dev/net/tun", 1);
   7.136 +    }
   7.137 +  // now, crate a tap device.
   7.138 +  struct ifreq ifr;
   7.139 +  // make sure that the tap device will not send us the tun_pi header.
   7.140 +  ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
   7.141 +  ifr.ifr_name[0] = 0; // allow the kernel to pick a device name.
   7.142 +  int status = ioctl (tap, TUNSETIFF, (void *) &ifr);
   7.143 +  if (status == -1)
   7.144 +    {
   7.145 +      EXIT_ERROR ("Could not allocate a tap device", 2);
   7.146 +    }
   7.147 +  std::string tapDeviceName = (char *)ifr.ifr_name;
   7.148 +  LOG ("Allocated TAP device=" << tapDeviceName);
   7.149 +
   7.150 +  // set its hardware address to something we know will be unique within the simulation
   7.151 +  ifr.ifr_hwaddr.sa_family = 1; // this is ARPHRD_ETHER from if_arp.h
   7.152 +  AsciiToMac48 (mac_addr, (uint8_t*)ifr.ifr_hwaddr.sa_data);
   7.153 +  status = ioctl (tap, SIOCSIFHWADDR, &ifr);
   7.154 +  if (status == -1)
   7.155 +    {
   7.156 +      EXIT_ERROR ("Could not set hardware address=" << mac_addr << " for=" << (char *)ifr.ifr_name, 3);
   7.157 +    }
   7.158 +  LOG ("device=" << (char *)ifr.ifr_name << " addr=" << mac_addr);
   7.159 +
   7.160 +
   7.161 +  // The ip address must be set using an AF_INET socket.
   7.162 +  int fd = socket (AF_INET, SOCK_DGRAM, 0);
   7.163 +
   7.164 +  // set interface up.
   7.165 +  status = ioctl (fd, SIOCGIFFLAGS, &ifr);
   7.166 +  if (status == -1)
   7.167 +    {
   7.168 +      EXIT_ERROR ("Could not get flags for interface=" << (char *)ifr.ifr_name, 4);
   7.169 +    }
   7.170 +  ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
   7.171 +  status = ioctl (fd, SIOCSIFFLAGS, &ifr);
   7.172 +  if (status == -1)
   7.173 +    {
   7.174 +      EXIT_ERROR ("Could not bring interface " << (char *)ifr.ifr_name << " up", 5);
   7.175 +    }
   7.176 +  LOG ("device=" << (char *)ifr.ifr_name << " is up");
   7.177 +
   7.178 +
   7.179 +  // set its ip address.
   7.180 +  SetInetAddress (&ifr.ifr_addr, AsciiToIpv4 (ip));
   7.181 +  status = ioctl (fd, SIOCSIFADDR, &ifr);
   7.182 +  if (status == -1)
   7.183 +    {
   7.184 +      EXIT_ERROR ("Could not set ip address=" << ip << " for=" <<  (char *)ifr.ifr_name, 6);
   7.185 +    }
   7.186 +  LOG ("device=" << (char *)ifr.ifr_name << " addr=" << ip);
   7.187 +
   7.188 +  // set its ip mask to be /32
   7.189 +  SetInetAddress (&ifr.ifr_netmask, 0xffffffff);
   7.190 +  status = ioctl (fd, SIOCSIFNETMASK, &ifr);
   7.191 +  if (status == -1)
   7.192 +    {
   7.193 +      EXIT_ERROR ("Could not set ip mask=" << netmask << " for=" <<  (char *)ifr.ifr_name, 7);
   7.194 +    }
   7.195 +  LOG ("device=" << (char *)ifr.ifr_name << " mask=" << netmask); 
   7.196 +
   7.197 +  // add routing entry for gateway.
   7.198 +  struct rtentry rt;
   7.199 +  SetInetAddress (&rt.rt_dst, AsciiToIpv4 (gw));
   7.200 +  SetInetAddress (&rt.rt_genmask, 0xffffffff);
   7.201 +  rt.rt_flags = RTF_UP;
   7.202 +  rt.rt_metric = 2;
   7.203 +  rt.rt_dev = (char*)tapDeviceName.c_str ();
   7.204 +  status = ioctl (fd, SIOCADDRT, &rt);
   7.205 +  if (status == -1)
   7.206 +    {
   7.207 +      EXIT_ERROR ("Could not add routing table entry", 8);
   7.208 +    }
   7.209 +  LOG ("added routing table entry for gw.");
   7.210 +
   7.211 +  // add routing entry for subnet through gateway.
   7.212 +  uint32_t network = AsciiToIpv4 (ip) & AsciiToIpv4 (netmask);
   7.213 +  SetInetAddress (&rt.rt_dst, network);
   7.214 +  SetInetAddress (&rt.rt_gateway, AsciiToIpv4 (gw));
   7.215 +  SetInetAddress (&rt.rt_genmask, AsciiToIpv4 (netmask));
   7.216 +  rt.rt_flags = RTF_UP | RTF_GATEWAY;
   7.217 +  rt.rt_metric = 2;
   7.218 +  rt.rt_dev = (char*)tapDeviceName.c_str ();
   7.219 +  status = ioctl (fd, SIOCADDRT, &rt);
   7.220 +  if (status == -1)
   7.221 +    {
   7.222 +      EXIT_ERROR ("Could not add routing table entry", 9);
   7.223 +    }
   7.224 +  LOG ("added routing table entry for subnet.");
   7.225 +
   7.226 +  return tap;
   7.227 +}
   7.228 +
   7.229 +static struct sockaddr_un
   7.230 +DecodeFromString (const char *path, socklen_t *len)
   7.231 +{
   7.232 +  sockaddr_un un;
   7.233 +  uint8_t *buffer = (uint8_t *)&un;
   7.234 +  std::istringstream iss;
   7.235 +  iss.str (path);
   7.236 +  uint8_t n = 0;
   7.237 +  while (!iss.bad () && !iss.eof () && !iss.fail ())
   7.238 +    {
   7.239 +      char c;
   7.240 +      iss.read (&c, 1);
   7.241 +      uint32_t tmp;
   7.242 +      iss >> std::hex >> tmp;
   7.243 +      //LOG (std::hex << tmp);
   7.244 +      buffer[n] = tmp;
   7.245 +      n++;
   7.246 +    }
   7.247 +  *len = n;
   7.248 +  return un;
   7.249 +}
   7.250 +
   7.251 +static void
   7.252 +SendFd (const char *path, int fd)
   7.253 +{
   7.254 +  // send back configuration to caller.
   7.255 +  int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
   7.256 +  if (sock == -1)
   7.257 +    {
   7.258 +      EXIT_ERROR ("Socket creation", 10);
   7.259 +    }
   7.260 +  LOG ("Socket Created");
   7.261 +  
   7.262 +  socklen_t local_len;
   7.263 +  struct sockaddr_un local = DecodeFromString (path, &local_len);
   7.264 +  LOG ("len=" << local_len);
   7.265 +  int status = connect (sock, (struct sockaddr*)&local, local_len);
   7.266 +  if (status == -1)
   7.267 +    {
   7.268 +      EXIT_ERROR ("Could not connect to caller", 11);
   7.269 +    }
   7.270 +  LOG ("Socket Connected");
   7.271 +
   7.272 +  // we send a single byte whose content is meaningless.
   7.273 +  // we also return as ancillary data the tap file descriptor
   7.274 +  struct cmsghdr *cmsg;
   7.275 +  size_t msg_size = sizeof(int);
   7.276 +  char control[CMSG_SPACE(msg_size)];
   7.277 +  struct iovec iov;
   7.278 +  struct msghdr msg;
   7.279 +  char buffer = 0;
   7.280 +  iov.iov_base = &buffer;
   7.281 +  iov.iov_len = 1;
   7.282 +  msg.msg_name = 0;
   7.283 +  msg.msg_namelen = 0;
   7.284 +  msg.msg_iov = &iov;
   7.285 +  msg.msg_iovlen = 1;
   7.286 +  msg.msg_control = control;
   7.287 +  msg.msg_controllen = sizeof (control);
   7.288 +  msg.msg_flags = 0;
   7.289 +
   7.290 +  cmsg = CMSG_FIRSTHDR(&msg);
   7.291 +  cmsg->cmsg_level = SOL_SOCKET;
   7.292 +  cmsg->cmsg_type = SCM_RIGHTS;
   7.293 +  cmsg->cmsg_len = CMSG_LEN(msg_size);
   7.294 +  msg.msg_controllen = cmsg->cmsg_len;
   7.295 +
   7.296 +  int *fdptr = (int*) (CMSG_DATA(cmsg));
   7.297 +  *fdptr = fd;
   7.298 +
   7.299 +  ssize_t len = sendmsg(sock, &msg, 0);
   7.300 +  if (len == -1)
   7.301 +    {
   7.302 +      EXIT_ERROR ("Could not send SCM_RIGHTS", 12);
   7.303 +    }
   7.304 +  LOG ("Sent SCM_RIGHTS");
   7.305 +}
   7.306 +
   7.307 +
   7.308 +
   7.309 +
   7.310 +int main (int argc, char *argv[])
   7.311 +{
   7.312 +  char *path = 0;
   7.313 +  char *mac_addr = 0;
   7.314 +  char *ip_addr = 0;
   7.315 +  char *ip_gw = 0;
   7.316 +  char *ip_netmask = 0;
   7.317 +  char *stop = 0;
   7.318 +  argv++;
   7.319 +  argc--;
   7.320 +  while (argc > 0)
   7.321 +    {
   7.322 +      CHECK_ARG("path", path);
   7.323 +      CHECK_ARG("mac-addr", mac_addr);
   7.324 +      CHECK_ARG("ip-addr", ip_addr);
   7.325 +      CHECK_ARG("ip-gw", ip_gw);
   7.326 +      CHECK_ARG("ip-netmask", ip_netmask);
   7.327 +      CHECK_ARG("stop", stop);
   7.328 +      argv++;
   7.329 +      argc--;
   7.330 +    }
   7.331 +  
   7.332 +  int tap = CreateTap (mac_addr, ip_addr, ip_gw, ip_netmask);
   7.333 +
   7.334 +  if (stop)
   7.335 +    {
   7.336 +      while (1) {}
   7.337 +    }
   7.338 +
   7.339 +  SendFd (path, tap);
   7.340 +
   7.341 +  return 0;
   7.342 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/devices/emutap/tap-net-device.cc	Mon Oct 27 13:01:28 2008 -0700
     8.3 @@ -0,0 +1,323 @@
     8.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     8.5 +/*
     8.6 + * Copyright (c) 2008 INRIA
     8.7 + *
     8.8 + * This program is free software; you can redistribute it and/or modify
     8.9 + * it under the terms of the GNU General Public License version 2 as
    8.10 + * published by the Free Software Foundation;
    8.11 + *
    8.12 + * This program is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU General Public License
    8.18 + * along with this program; if not, write to the Free Software
    8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.20 + *
    8.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    8.22 + */
    8.23 +#include "tap-net-device.h"
    8.24 +#include "tap-manager-client.h"
    8.25 +#include "ns3/node.h"
    8.26 +#include "ns3/channel.h"
    8.27 +#include "ns3/packet.h"
    8.28 +#include "ns3/log.h"
    8.29 +#include "ns3/system-thread.h"
    8.30 +#include "ns3/realtime-simulator-impl.h"
    8.31 +#include "ns3/make-event.h"
    8.32 +#include "ns3/simulator.h"
    8.33 +#include "ns3/ethernet-header.h"
    8.34 +#include "ns3/trace-source-accessor.h"
    8.35 +#include "host-tap-net-device.h"
    8.36 +#include "tap-channel.h"
    8.37 +#include <errno.h>
    8.38 +#include <stdlib.h>
    8.39 +
    8.40 +NS_LOG_COMPONENT_DEFINE ("TapNetDevice");
    8.41 +
    8.42 +namespace ns3 {
    8.43 +
    8.44 +TypeId 
    8.45 +TapNetDevice::GetTypeId (void)
    8.46 +{
    8.47 +  static TypeId tid = TypeId ("ns3::TapNetDevice")
    8.48 +    .SetParent<NetDevice> ()
    8.49 +    .AddConstructor<TapNetDevice> ()
    8.50 +    .AddTraceSource ("Rx", "A packet has been received",
    8.51 +                     MakeTraceSourceAccessor (&TapNetDevice::m_rxTrace))
    8.52 +    .AddTraceSource ("Tx", "A packet has been sent",
    8.53 +                     MakeTraceSourceAccessor (&TapNetDevice::m_txTrace))
    8.54 +    .AddTraceSource ("Drop", "A packet has been dropped",
    8.55 +                     MakeTraceSourceAccessor (&TapNetDevice::m_dropTrace))
    8.56 +    ;
    8.57 +  return tid;
    8.58 +}
    8.59 +
    8.60 +TapNetDevice::TapNetDevice ()
    8.61 +  : m_node (0),
    8.62 +    m_mtu (0xffff),
    8.63 +    m_name (""),
    8.64 +    m_ifIndex (0),
    8.65 +    m_tap (-1)
    8.66 +{
    8.67 +  NS_LOG_FUNCTION (this);
    8.68 +}
    8.69 +
    8.70 +void 
    8.71 +TapNetDevice::SetChannel (Ptr<TapChannel> channel)
    8.72 +{
    8.73 +  m_channel = channel;
    8.74 +  m_channel->SetDevice (this);
    8.75 +}
    8.76 +
    8.77 +void 
    8.78 +TapNetDevice::SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
    8.79 +{
    8.80 +  NS_LOG_FUNCTION (this << ad << mask << gateway);
    8.81 +  NS_ASSERT (m_tap == -1);
    8.82 +
    8.83 +  Mac48Address hostMacAddress = m_channel->GetHostDevice ()->GetMacAddress ();
    8.84 +
    8.85 +  TapManagerClient manager;
    8.86 +  m_tap = manager.AllocateTap (hostMacAddress, ad, mask, gateway);
    8.87 +
    8.88 +  m_thread = Create<SystemThread> (MakeCallback (&TapNetDevice::ReadThread, this));
    8.89 +  m_thread->Start ();
    8.90 +}
    8.91 +
    8.92 +
    8.93 +void
    8.94 +TapNetDevice::ReadThread (void)
    8.95 +{
    8.96 +  NS_LOG_FUNCTION (this);
    8.97 +
    8.98 +  while (1)
    8.99 +    {
   8.100 +      uint8_t *buffer = (uint8_t *)malloc (0xffff);
   8.101 +      ssize_t bytesRead = read (m_tap, buffer, 0xffff);
   8.102 +      if (bytesRead == -1)
   8.103 +        {
   8.104 +          if (errno == EBADF || errno == EINTR)
   8.105 +            {
   8.106 +              // the device was closed from under us by ::DoDispose
   8.107 +              return;
   8.108 +            }
   8.109 +          NS_FATAL_ERROR ("Error reading from tap device: errno=" << strerror (errno));
   8.110 +        }
   8.111 +      // Note: we purposedly don't use a smart pointer to manage this packet
   8.112 +      // because the want to hand over ownership of this packet to the ForwardUp
   8.113 +      // method.
   8.114 +      DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->
   8.115 +        ScheduleRealtimeNow (MakeEvent (&TapNetDevice::ForwardUp, this, buffer, (uint32_t)bytesRead));
   8.116 +    }
   8.117 +}
   8.118 +
   8.119 +void
   8.120 +TapNetDevice::ForwardUp (uint8_t *buffer, uint32_t size)
   8.121 +{
   8.122 +  NS_LOG_FUNCTION (this << buffer << size);
   8.123 +
   8.124 +  // swallow packet reference in smart pointer.
   8.125 +  Ptr<Packet> packet = Create<Packet> (buffer, size);
   8.126 +  free (buffer);
   8.127 +  Ptr<Packet> copy = packet->Copy ();
   8.128 +
   8.129 +  EthernetHeader header = EthernetHeader (false);
   8.130 +  packet->RemoveHeader (header);
   8.131 +
   8.132 +  uint16_t protocol = header.GetLengthType ();
   8.133 +  Mac48Address to = header.GetDestination ();
   8.134 +  Mac48Address from = header.GetSource ();
   8.135 +  
   8.136 +  NetDevice::PacketType packetType;
   8.137 +  if (to == m_address)
   8.138 +    {
   8.139 +      packetType = NetDevice::PACKET_HOST;
   8.140 +    }
   8.141 +  else if (to.IsBroadcast ())
   8.142 +    {
   8.143 +      packetType = NetDevice::PACKET_HOST;
   8.144 +    }
   8.145 +  else if (to.IsMulticast ())
   8.146 +    {
   8.147 +      packetType = NetDevice::PACKET_MULTICAST;
   8.148 +    }
   8.149 +  else 
   8.150 +    {
   8.151 +      packetType = NetDevice::PACKET_OTHERHOST;
   8.152 +    }
   8.153 +  m_rxTrace (copy, from, to);
   8.154 +  if (packetType != NetDevice::PACKET_OTHERHOST)
   8.155 +    {
   8.156 +      m_rxCallback (this, packet, protocol, from);
   8.157 +    }
   8.158 +  if (!m_promiscCallback.IsNull ())
   8.159 +    {
   8.160 +      m_promiscCallback (this, packet, protocol, from, to, packetType);
   8.161 +    }
   8.162 +}
   8.163 +
   8.164 +void 
   8.165 +TapNetDevice::SetAddress (Mac48Address address)
   8.166 +{
   8.167 +  m_address = address;
   8.168 +}
   8.169 +
   8.170 +void 
   8.171 +TapNetDevice::SetName(const std::string name)
   8.172 +{
   8.173 +  m_name = name;
   8.174 +}
   8.175 +std::string 
   8.176 +TapNetDevice::GetName(void) const
   8.177 +{
   8.178 +  return m_name;
   8.179 +}
   8.180 +void 
   8.181 +TapNetDevice::SetIfIndex(const uint32_t index)
   8.182 +{
   8.183 +  m_ifIndex = index;
   8.184 +}
   8.185 +uint32_t 
   8.186 +TapNetDevice::GetIfIndex(void) const
   8.187 +{
   8.188 +  return m_ifIndex;
   8.189 +}
   8.190 +Ptr<Channel> 
   8.191 +TapNetDevice::GetChannel (void) const
   8.192 +{
   8.193 +  return m_channel;
   8.194 +}
   8.195 +Address 
   8.196 +TapNetDevice::GetAddress (void) const
   8.197 +{
   8.198 +  return m_address;
   8.199 +}
   8.200 +bool 
   8.201 +TapNetDevice::SetMtu (const uint16_t mtu)
   8.202 +{
   8.203 +  m_mtu = mtu;
   8.204 +  return true;
   8.205 +}
   8.206 +uint16_t 
   8.207 +TapNetDevice::GetMtu (void) const
   8.208 +{
   8.209 +  return m_mtu;
   8.210 +}
   8.211 +bool 
   8.212 +TapNetDevice::IsLinkUp (void) const
   8.213 +{
   8.214 +  return true;
   8.215 +}
   8.216 +void 
   8.217 +TapNetDevice::SetLinkChangeCallback (Callback<void> callback)
   8.218 +{}
   8.219 +bool 
   8.220 +TapNetDevice::IsBroadcast (void) const
   8.221 +{
   8.222 +  return true;
   8.223 +}
   8.224 +Address
   8.225 +TapNetDevice::GetBroadcast (void) const
   8.226 +{
   8.227 +  return Mac48Address ("ff:ff:ff:ff:ff:ff");
   8.228 +}
   8.229 +bool 
   8.230 +TapNetDevice::IsMulticast (void) const
   8.231 +{
   8.232 +  return true;
   8.233 +}
   8.234 +Address 
   8.235 +TapNetDevice::GetMulticast (void) const
   8.236 +{
   8.237 +  return Mac48Address::GetMulticastPrefix ();
   8.238 +}
   8.239 +Address 
   8.240 +TapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
   8.241 +{
   8.242 +  return Mac48Address::GetMulticast (multicastGroup);
   8.243 +}
   8.244 +bool 
   8.245 +TapNetDevice::IsPointToPoint (void) const
   8.246 +{
   8.247 +  return false;
   8.248 +}
   8.249 +bool 
   8.250 +TapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
   8.251 +{
   8.252 +  NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
   8.253 +  return SendFrom (packet, m_address, dest, protocolNumber);
   8.254 +}
   8.255 +bool 
   8.256 +TapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
   8.257 +{
   8.258 +  NS_LOG_FUNCTION (this << packet << source << dest << protocolNumber);
   8.259 +  Mac48Address to = Mac48Address::ConvertFrom (dest);
   8.260 +  Mac48Address from = Mac48Address::ConvertFrom (source);
   8.261 +
   8.262 +  EthernetHeader header = EthernetHeader (false);
   8.263 +  header.SetSource (from);
   8.264 +  header.SetDestination (to);
   8.265 +  header.SetLengthType (protocolNumber);
   8.266 +  packet->AddHeader (header);
   8.267 +
   8.268 +  ssize_t written = write (m_tap, packet->PeekData (), packet->GetSize ());
   8.269 +  if (written == -1 || written != (ssize_t)packet->GetSize ())
   8.270 +    {
   8.271 +      m_dropTrace (packet, from, to);
   8.272 +      return false;
   8.273 +    }
   8.274 +
   8.275 +  m_txTrace (packet, from, to);
   8.276 +  
   8.277 +  return true;
   8.278 +}
   8.279 +
   8.280 +Ptr<Node> 
   8.281 +TapNetDevice::GetNode (void) const
   8.282 +{
   8.283 +  return m_node;
   8.284 +}
   8.285 +void 
   8.286 +TapNetDevice::SetNode (Ptr<Node> node)
   8.287 +{
   8.288 +  m_node = node;
   8.289 +}
   8.290 +bool 
   8.291 +TapNetDevice::NeedsArp (void) const
   8.292 +{
   8.293 +  return true;
   8.294 +}
   8.295 +void 
   8.296 +TapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
   8.297 +{
   8.298 +  m_rxCallback = cb;
   8.299 +}
   8.300 +
   8.301 +void
   8.302 +TapNetDevice::DoDispose (void)
   8.303 +{
   8.304 +  NS_LOG_FUNCTION (this);
   8.305 +  close (m_tap);
   8.306 +  m_thread->Join ();
   8.307 +  m_thread = 0;
   8.308 +  m_node = 0;
   8.309 +  m_channel = 0;
   8.310 +  NetDevice::DoDispose ();
   8.311 +}
   8.312 +
   8.313 +
   8.314 +void
   8.315 +TapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
   8.316 +{
   8.317 +  m_promiscCallback = cb;
   8.318 +}
   8.319 +
   8.320 +bool
   8.321 +TapNetDevice::SupportsSendFrom (void) const
   8.322 +{
   8.323 +  return true;
   8.324 +}
   8.325 +
   8.326 +} // namespace ns3
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/devices/emutap/tap-net-device.h	Mon Oct 27 13:01:28 2008 -0700
     9.3 @@ -0,0 +1,103 @@
     9.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     9.5 +/*
     9.6 + * Copyright (c) 2008 INRIA
     9.7 + *
     9.8 + * This program is free software; you can redistribute it and/or modify
     9.9 + * it under the terms of the GNU General Public License version 2 as
    9.10 + * published by the Free Software Foundation;
    9.11 + *
    9.12 + * This program is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU General Public License
    9.18 + * along with this program; if not, write to the Free Software
    9.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.20 + *
    9.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    9.22 + */
    9.23 +#ifndef TAP_NET_DEVICE_H
    9.24 +#define TAP_NET_DEVICE_H
    9.25 +
    9.26 +#include "ns3/net-device.h"
    9.27 +#include "ns3/mac48-address.h"
    9.28 +#include "ns3/traced-callback.h"
    9.29 +#include <stdint.h>
    9.30 +#include <string>
    9.31 +
    9.32 +namespace ns3 {
    9.33 +
    9.34 +class Node;
    9.35 +class SystemThread;
    9.36 +class TapChannel;
    9.37 +
    9.38 +/**
    9.39 + * \ingroup netdevice
    9.40 + * 
    9.41 + * \brief a NetDevice to get packets to and from a host tap device.
    9.42 + */
    9.43 +class TapNetDevice : public NetDevice
    9.44 +{
    9.45 +public:
    9.46 +  static TypeId GetTypeId (void);
    9.47 +  TapNetDevice ();
    9.48 +
    9.49 +  void SetAddress (Mac48Address address);
    9.50 +
    9.51 +  void SetChannel (Ptr<TapChannel> channel);
    9.52 +
    9.53 +  void SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway);
    9.54 +
    9.55 +  // inherited from NetDevice base class.
    9.56 +  virtual void SetName(const std::string name);
    9.57 +  virtual std::string GetName(void) const;
    9.58 +  virtual void SetIfIndex(const uint32_t index);
    9.59 +  virtual uint32_t GetIfIndex(void) const;
    9.60 +  virtual Ptr<Channel> GetChannel (void) const;
    9.61 +  virtual Address GetAddress (void) const;
    9.62 +  virtual bool SetMtu (const uint16_t mtu);
    9.63 +  virtual uint16_t GetMtu (void) const;
    9.64 +  virtual bool IsLinkUp (void) const;
    9.65 +  virtual void SetLinkChangeCallback (Callback<void> callback);
    9.66 +  virtual bool IsBroadcast (void) const;
    9.67 +  virtual Address GetBroadcast (void) const;
    9.68 +  virtual bool IsMulticast (void) const;
    9.69 +  virtual Address GetMulticast (void) const;
    9.70 +  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
    9.71 +  virtual bool IsPointToPoint (void) const;
    9.72 +  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
    9.73 +  virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
    9.74 +  virtual Ptr<Node> GetNode (void) const;
    9.75 +  virtual void SetNode (Ptr<Node> node);
    9.76 +  virtual bool NeedsArp (void) const;
    9.77 +  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
    9.78 +  virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
    9.79 +  virtual bool SupportsSendFrom (void) const;
    9.80 +
    9.81 +protected:
    9.82 +  virtual void DoDispose (void);
    9.83 +private:
    9.84 +  void Receive (Ptr<Packet> packet, uint16_t protocol, 
    9.85 +                Mac48Address to, Mac48Address from);
    9.86 +  void ForwardUp (uint8_t *buffer, uint32_t size);
    9.87 +  void ReadThread (void);
    9.88 +
    9.89 +  NetDevice::ReceiveCallback m_rxCallback;
    9.90 +  NetDevice::PromiscReceiveCallback m_promiscCallback;
    9.91 +  Ptr<Node> m_node;
    9.92 +  uint16_t m_mtu;
    9.93 +  std::string m_name;
    9.94 +  uint32_t m_ifIndex;
    9.95 +  Mac48Address m_address;
    9.96 +  int m_tap;
    9.97 +  Ptr<SystemThread> m_thread;
    9.98 +  TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_rxTrace;
    9.99 +  TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_txTrace;
   9.100 +  TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_dropTrace;
   9.101 +  Ptr<TapChannel> m_channel;
   9.102 +};
   9.103 +
   9.104 +} // namespace ns3
   9.105 +
   9.106 +#endif /* TAP_NET_DEVICE_H */
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/devices/emutap/wscript	Mon Oct 27 13:01:28 2008 -0700
    10.3 @@ -0,0 +1,26 @@
    10.4 +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
    10.5 +
    10.6 +
    10.7 +def build(bld):
    10.8 +    obj = bld.create_suid_program('ns3-tap-manager')
    10.9 +    obj.source = [
   10.10 +       'tap-manager.cc',
   10.11 +       ]
   10.12 +
   10.13 +    module = bld.create_ns3_module('emutap', ['node'])
   10.14 +    module.uselib = 'CAP'
   10.15 +    module.source = [
   10.16 +    'tap-net-device.cc',
   10.17 +    'tap-manager-client.cc',
   10.18 +    'tap-channel.cc',
   10.19 +    'host-tap-net-device.cc',
   10.20 +    ]
   10.21 +    headers = bld.create_obj('ns3header')
   10.22 +    headers.module = 'emutap'
   10.23 +    headers.source = [
   10.24 +    'tap-net-device.h',
   10.25 +    'host-tap-net-device.h',
   10.26 +    'tap-channel.h',
   10.27 +    ]
   10.28 +
   10.29 +
    11.1 --- a/src/wscript	Mon Oct 27 16:40:03 2008 +0100
    11.2 +++ b/src/wscript	Mon Oct 27 13:01:28 2008 -0700
    11.3 @@ -19,6 +19,8 @@
    11.4      'internet-stack',
    11.5      'devices/point-to-point',
    11.6      'devices/csma',
    11.7 +    'devices/bridge',
    11.8 +    'devices/emutap',
    11.9      'applications/onoff',
   11.10      'applications/packet-sink',
   11.11      'applications/udp-echo',
   11.12 @@ -27,7 +29,6 @@
   11.13      'mobility',
   11.14      'devices/wifi',
   11.15      'helper',
   11.16 -    'devices/bridge',
   11.17      'contrib/stats',
   11.18      )
   11.19  
    12.1 --- a/wscript	Mon Oct 27 16:40:03 2008 +0100
    12.2 +++ b/wscript	Mon Oct 27 13:01:28 2008 -0700
    12.3 @@ -12,6 +12,7 @@
    12.4  import Params
    12.5  import Object
    12.6  import ccroot
    12.7 +import Task
    12.8  
    12.9  Params.g_autoconfig = 1
   12.10  
   12.11 @@ -166,6 +167,10 @@
   12.12                     help=('For regression testing, only run/generate the indicated regression tests, '
   12.13                           'specified as a comma separated list of test names'),
   12.14                     dest='regression_tests', type="string")
   12.15 +    opt.add_option('--disable-sudo',
   12.16 +                   help=('Do not attempt to use sudo to setup suid bits on ns3 executables.'),
   12.17 +                   dest='disable_sudo', action='store_true',
   12.18 +                   default=False)
   12.19  
   12.20      # options provided in a script in a subdirectory named "src"
   12.21      opt.sub_options('src')
   12.22 @@ -275,6 +280,9 @@
   12.23      # we cannot run regression tests without diff
   12.24      conf.find_program('diff', var='DIFF')
   12.25  
   12.26 +    # for suid bits
   12.27 +    conf.find_program('sudo', var='SUDO')
   12.28 +
   12.29      # we cannot pull regression traces without mercurial
   12.30      conf.find_program('hg', var='MERCURIAL')
   12.31  
   12.32 @@ -288,6 +296,41 @@
   12.33          print "%-30s: %s" % (caption, status)
   12.34  
   12.35  
   12.36 +class SuidBuildTask(Task.TaskBase):
   12.37 +    """task that makes a binary Suid
   12.38 +    """
   12.39 +    def __init__(self, bld, program):
   12.40 +        self.m_display = 'build-suid'
   12.41 +        self.prio = 1000 # build after the rest of ns-3
   12.42 +        self.__program = program
   12.43 +        self.__env = bld.env ()
   12.44 +        super(SuidBuildTask, self).__init__()
   12.45 +
   12.46 +    def run(self):
   12.47 +        try:
   12.48 +            program_obj = _find_program(self.__program.target, self.__env)
   12.49 +        except ValueError, ex:
   12.50 +            Params.fatal(str(ex))
   12.51 +
   12.52 +        try:
   12.53 +            program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj))
   12.54 +        except AttributeError:
   12.55 +            Params.fatal("%s does not appear to be a program" % (program_name,))
   12.56 +
   12.57 +        filename = program_node.abspath(self.__env)
   12.58 +        os.system ('sudo chown root ' + filename)
   12.59 +        os.system ('sudo chmod u+s ' + filename)
   12.60 +
   12.61 +def create_suid_program(bld, name):
   12.62 +    program = bld.create_obj('cpp', 'program')
   12.63 +    program.is_ns3_program = True
   12.64 +    program.module_deps = list()
   12.65 +    program.name = name
   12.66 +    program.target = name
   12.67 +    if bld.env ()['SUDO'] and not Params.g_options.disable_sudo:
   12.68 +        SuidBuildTask (bld, program)
   12.69 +    return program
   12.70 +
   12.71  def create_ns3_program(bld, name, dependencies=('simulator',)):
   12.72      program = bld.create_obj('cpp', 'program')
   12.73      program.is_ns3_program = True
   12.74 @@ -340,6 +383,7 @@
   12.75  
   12.76      Params.g_cwd_launch = Params.g_build.m_curdirnode.abspath()
   12.77      bld.create_ns3_program = types.MethodType(create_ns3_program, bld)
   12.78 +    bld.create_suid_program = types.MethodType(create_suid_program, bld)
   12.79      variant_name = bld.env_of_name('default')['NS3_ACTIVE_VARIANT']
   12.80      variant_env = bld.env_of_name(variant_name)
   12.81      bld.m_allenvs['default'] = variant_env # switch to the active variant