Add TapNetDevice (formerly known as VirtualNetDevice)
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Sun, 24 May 2009 16:18:20 +0100
changeset 4536 dee7215f0334
parent 4457 1b45505f9a52
child 4537 118338cd9f61
Add TapNetDevice (formerly known as VirtualNetDevice)
src/devices/tap-net-device/tap-net-device.cc
src/devices/tap-net-device/tap-net-device.h
src/devices/tap-net-device/waf
src/devices/tap-net-device/wscript
src/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/tap-net-device/tap-net-device.cc	Sun May 24 16:18:20 2009 +0100
@@ -0,0 +1,271 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author:  Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#include "ns3/log.h"
+#include "ns3/queue.h"
+#include "ns3/simulator.h"
+#include "ns3/mac48-address.h"
+#include "ns3/llc-snap-header.h"
+#include "ns3/error-model.h"
+#include "tap-net-device.h"
+#include "ns3/channel.h"
+#include "ns3/trace-source-accessor.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("TapNetDevice");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TapNetDevice);
+
+TypeId
+TapNetDevice::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TapNetDevice")
+    .SetParent<NetDevice> ()
+    .AddConstructor<TapNetDevice> ()
+    .AddTraceSource ("Rx", "Received payload from the MAC layer.",
+                     MakeTraceSourceAccessor (&TapNetDevice::m_rxTrace))
+    .AddTraceSource ("Tx", "Send payload to the MAC layer.",
+                     MakeTraceSourceAccessor (&TapNetDevice::m_txTrace))
+    ;
+  return tid;
+}
+
+TapNetDevice::TapNetDevice ()
+{
+  m_needsArp = false;
+  m_supportsSendFrom = true;
+  m_mtu = 65535;
+}
+
+
+void
+TapNetDevice::SetSendFromCallback (SendFromCallback sendCb)
+{
+  m_sendCb = sendCb;
+}
+
+void
+TapNetDevice::SetNeedsArp (bool needsArp)
+{
+  m_needsArp = needsArp;
+}
+
+void
+TapNetDevice::SetSupportsSendFrom (bool supportsSendFrom)
+{
+  m_supportsSendFrom = supportsSendFrom;
+}
+
+bool
+TapNetDevice::SetMtu (const uint16_t mtu)
+{
+  m_mtu = mtu;
+  return true;
+}
+
+
+TapNetDevice::~TapNetDevice()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+
+void TapNetDevice::DoDispose()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NetDevice::DoDispose ();
+}
+
+bool
+TapNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol, const Address &address)
+{
+  if (m_rxCallback (this, packet, protocol, address))
+    {
+      m_rxTrace (packet);
+      return true;
+    }
+  return false;
+}
+
+bool
+TapNetDevice::PromiscReceive (Ptr<Packet> packet, uint16_t protocol,
+                              const Address &source, const Address &destination,
+                              PacketType packetType)
+{
+  if (m_promiscRxCallback (this, packet, protocol, source, destination, packetType))
+    {
+      m_rxTrace (packet);
+      return true;
+    }
+  return false;
+}
+
+
+void
+TapNetDevice::SetName (const std::string name)
+{
+  m_name = name;
+}
+
+std::string
+TapNetDevice::GetName (void) const
+{
+  return m_name;
+}
+
+void
+TapNetDevice::SetIfIndex (const uint32_t index)
+{
+  m_index = index;
+}
+
+uint32_t
+TapNetDevice::GetIfIndex (void) const
+{
+  return m_index;
+}
+
+Ptr<Channel>
+TapNetDevice::GetChannel (void) const
+{
+  return Ptr<Channel> ();
+}
+
+Address
+TapNetDevice::GetAddress (void) const
+{
+  return Mac48Address ();
+}
+
+uint16_t
+TapNetDevice::GetMtu (void) const
+{
+  return m_mtu;
+}
+
+bool
+TapNetDevice::IsLinkUp (void) const
+{
+  return true;
+}
+
+void
+TapNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+}
+
+bool
+TapNetDevice::IsBroadcast (void) const
+{
+  return m_needsArp;
+}
+
+Address
+TapNetDevice::GetBroadcast (void) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+
+bool
+TapNetDevice::IsMulticast (void) const
+{
+  return false;
+}
+
+Address TapNetDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+
+Address TapNetDevice::GetMulticast (Ipv6Address addr) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");  
+}
+
+
+bool
+TapNetDevice::IsPointToPoint (void) const
+{
+  return true;
+}
+
+bool
+TapNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+  return SendFrom (packet, GetAddress (), dest, protocolNumber);
+}
+
+bool
+TapNetDevice::SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
+{
+  NS_FATAL_ERROR ("not implemented");
+  if (m_sendCb (packet, source, dest, protocolNumber))
+    {
+      m_txTrace (packet);
+      return true;
+    }
+  return false;
+}
+
+Ptr<Node>
+TapNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+
+void
+TapNetDevice::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+bool
+TapNetDevice::NeedsArp (void) const
+{
+  return m_needsArp;
+}
+
+void
+TapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
+}
+
+void
+TapNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
+{
+  m_promiscRxCallback = cb;
+}
+
+bool
+TapNetDevice::SupportsSendFrom () const
+{
+  return m_supportsSendFrom;
+}
+
+bool TapNetDevice::IsBridge (void) const
+{
+  return false;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/tap-net-device/tap-net-device.h	Sun May 24 16:18:20 2009 +0100
@@ -0,0 +1,166 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#ifndef TAP_NET_DEVICE_H
+#define TAP_NET_DEVICE_H
+
+#include "ns3/address.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/ptr.h"
+#include "ns3/traced-callback.h"
+
+namespace ns3 {
+
+
+/**
+ * \class TapNetDevice
+ * \brief A virtual device, similar to Linux TAP interfaces.
+ *
+ * A TapNetDevice is a "virtual" NetDevice implementation which
+ * delegates to a user callback (see method SetSendFromCallback()) the
+ * task of actually transmitting a packet.  It also allows the user
+ * code to inject the packet as if it had been received by the
+ * TapNetDevice.  Together, these features allow one to build tunnels.
+ * For instance, by transmitting packets into a UDP socket we end up
+ * building an IP-over-UDP-over-IP tunnel.
+ *
+ * The same thing could be accomplished by subclassing NetDevice
+ * directly.  However, TapNetDevice is usually much simpler to program
+ * than a NetDevice subclass.
+ */
+class TapNetDevice : public NetDevice
+{
+public:
+  typedef Callback<bool, Ptr<Packet>, const Address&, const Address&, uint16_t> SendFromCallback;
+
+  static TypeId GetTypeId (void);
+  TapNetDevice ();
+
+  virtual ~TapNetDevice ();
+
+  /**
+   * \brief Set the user callback to be called when a L2 packet is to be transmitted
+   * \param transmitCb the new transmit callback
+   */
+  void SetSendFromCallback (SendFromCallback transmitCb);
+
+  /**
+   * \brief Configure whether the virtual device needs ARP
+   *
+   * \param needsArp the the 'needs arp' value that will be returned
+   * by the NeedsArp() method.  The method IsBroadcast() will also
+   * return this value.
+   */
+  void SetNeedsArp (bool needsArp);
+
+  /**
+   * \brief Configure whether the virtual device supports SendFrom
+   */
+  void SetSupportsSendFrom (bool supportsSendFrom);
+
+  /**
+   * \brief Configure the reported MTU for the virtual device. The
+   * default value is 65535.
+   * \return whether the MTU value was within legal bounds
+   */
+  bool SetMtu (const uint16_t mtu);
+
+
+  /**
+   * \param p packet sent from below up to Network Device
+   * \param protocol Protocol type
+   * \param source the address of the sender of this packet.
+   * \returns true if the packet was forwarded successfully,
+   *          false otherwise.
+   *
+   * Forward a "virtually received" packet up the node's protocol
+   * stack.
+   */
+  bool Receive (Ptr<Packet> packet, uint16_t protocol, const Address &source);
+
+
+  /**
+   * \param p packet sent from below up to Network Device
+   * \param protocol Protocol type
+   * \param source the address of the sender of this packet.
+   * \param destination the address of the receiver of this packet.
+   * \param packetType type of packet received (broadcast/multicast/unicast/otherhost)
+   * \returns true if the packet was forwarded successfully, false otherwise.
+   *
+   * Forward a "virtually received (in promiscuous mode)" packet up
+   * the node's protocol stack.
+   */
+  bool PromiscReceive (Ptr<Packet> packet, uint16_t protocol,
+                       const Address &source, const Address &destination,
+                       PacketType packetType);
+
+
+  // inherited from NetDevice base class.
+  virtual void SetName(const std::string name);
+  virtual std::string GetName(void) const;
+  virtual void SetIfIndex(const uint32_t index);
+  virtual uint32_t GetIfIndex(void) const;
+  virtual Ptr<Channel> GetChannel (void) const;
+  virtual Address GetAddress (void) const;
+  virtual uint16_t GetMtu (void) const;
+  virtual bool IsLinkUp (void) const;
+  virtual void SetLinkChangeCallback (Callback<void> callback);
+  virtual bool IsBroadcast (void) const;
+  virtual Address GetBroadcast (void) const;
+  virtual bool IsMulticast (void) const;
+  virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+  virtual Address GetMulticast (Ipv6Address addr) const;
+  virtual bool IsPointToPoint (void) const;
+  virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
+  virtual Ptr<Node> GetNode (void) const;
+  virtual void SetNode (Ptr<Node> node);
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+  virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
+  virtual bool SupportsSendFrom () const;
+  virtual bool IsBridge (void) const;
+
+protected:
+
+  virtual void DoDispose (void);
+
+private:
+
+  SendFromCallback m_sendCb;
+  TracedCallback<Ptr<const Packet> > m_rxTrace;
+  TracedCallback<Ptr<const Packet> > m_txTrace;
+  Ptr<Node> m_node;
+  ReceiveCallback m_rxCallback;
+  PromiscReceiveCallback m_promiscRxCallback;
+  std::string m_name;
+  uint32_t m_index;
+  uint16_t m_mtu;
+  bool m_needsArp;
+  bool m_supportsSendFrom;
+};
+
+}; // namespace ns3
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/tap-net-device/waf	Sun May 24 16:18:20 2009 +0100
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../waf "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/tap-net-device/wscript	Sun May 24 16:18:20 2009 +0100
@@ -0,0 +1,14 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+    module = bld.create_ns3_module('tap-net-device', ['node'])
+    module.source = [
+        'tap-net-device.cc',
+        ]
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'tap-net-device'
+    headers.source = [
+        'tap-net-device.h',
+        ]
+
--- a/src/wscript	Sun May 24 11:39:41 2009 +0100
+++ b/src/wscript	Sun May 24 16:18:20 2009 +0100
@@ -23,6 +23,7 @@
     'devices/emu',
     'devices/bridge',
     'devices/tap-bridge',
+    'devices/tap-net-device',
     'applications/onoff',
     'applications/packet-sink',
     'applications/udp-echo',