/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2008 University of Washington
*
* 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
*/
#ifndef EMU_NET_DEVICE_H
#define EMU_NET_DEVICE_H
#include <cstring>
#include "ns3/address.h"
#include "ns3/net-device.h"
#include "ns3/node.h"
#include "ns3/callback.h"
#include "ns3/packet.h"
#include "ns3/traced-callback.h"
#include "ns3/event-id.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/ptr.h"
#include "ns3/mac48-address.h"
#include "ns3/system-thread.h"
#include "ns3/system-mutex.h"
namespace ns3 {
class Queue;
/**
* \defgroup emu EmuNetDevice
* This section documents the API of the ns-3 emu module. For a generic functional description, please refer to the ns-3 manual.
*/
/**
* \ingroup emu
* \class EmuNetDevice
* \brief A Device for an Emu Network Link.
*/
class EmuNetDevice : public NetDevice
{
public:
static TypeId GetTypeId (void);
/**
* Enumeration of the types of packets supported in the class.
*/
enum EncapsulationMode {
ILLEGAL, /**< Encapsulation mode not set */
DIX, /**< DIX II / Ethernet II packet */
LLC, /**< 802.2 LLC/SNAP Packet*/
};
/**
* Construct a EmuNetDevice
*
* This is the constructor for the EmuNetDevice. It takes as a
*/
EmuNetDevice ();
/**
* Destroy a EmuNetDevice
*
* This is the destructor for the EmuNetDevice.
*/
virtual ~EmuNetDevice ();
/**
* Set the Data Rate used for transmission of packets.
*
* @see Attach ()
* @param bps the data rate at which this object operates
*/
void SetDataRate (DataRate bps);
/**
* Set a start time for the device.
*
* @param tStart the start time
*/
void Start (Time tStart);
/**
* Set a stop time for the device.
*
* @param tStop the stop time
*/
void Stop (Time tStop);
/**
* Attach a queue to the EmuNetDevice.
*
* The EmuNetDevice "owns" a queue that implements a queueing
* method such as DropTail or RED.
*
* @see Queue
* @see DropTailQueue
* @param queue Ptr to the new queue.
*/
void SetQueue (Ptr<Queue> queue);
/**
* Get a copy of the attached Queue.
*
* @returns Ptr to the queue.
*/
Ptr<Queue> GetQueue (void) const;
//
// Pure virtual methods inherited from NetDevice we must implement.
//
virtual void SetIfIndex (const uint32_t index);
virtual uint32_t GetIfIndex (void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);
virtual uint16_t GetMtu (void) const;
virtual bool IsLinkUp (void) const;
virtual void AddLinkChangeCallback (Callback<void> callback);
virtual bool IsBroadcast (void) const;
virtual Address GetBroadcast (void) const;
virtual bool IsMulticast (void) const;
/**
* \brief Make and return a MAC multicast address using the provided
* multicast group
*
* RFC 1112 says that an Ipv4 host group address is mapped to an Ethernet
* multicast address by placing the low-order 23-bits of the IP address into
* the low-order 23 bits of the Ethernet multicast address
* 01-00-5E-00-00-00 (hex).
*
* This method performs the multicast address creation function appropriate
* to an EUI-48-based CSMA device. This MAC address is encapsulated in an
* abstract Address to avoid dependencies on the exact address format.
*
* \param multicastGroup The IP address for the multicast group destination
* of the packet.
* \return The MAC multicast Address used to send packets to the provided
* multicast group.
*
* \see Ipv4Address
* \see Mac48Address
* \see Address
*/
virtual Address GetMulticast (Ipv4Address multicastGroup) const;
/**
* \brief Get the MAC multicast address corresponding
* to the IPv6 address provided.
* \param addr IPv6 address
* \return the MAC multicast address
* \warning Calling this method is invalid if IsMulticast returns not true.
*/
virtual Address GetMulticast (Ipv6Address addr) const;
/**
* Is this a point to point link?
* \returns false.
*/
virtual bool IsPointToPoint (void) const;
/**
* Is this a bridge?
* \returns false.
*/
virtual bool IsBridge (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 (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
/**
* Set the encapsulation mode of this device.
*
* \param mode The encapsulation mode of this device.
*
* \see SetFrameSize
*/
void SetEncapsulationMode (EmuNetDevice::EncapsulationMode mode);
/**
* Get the encapsulation mode of this device.
*
* \returns The encapsulation mode of this device.
*/
EmuNetDevice::EncapsulationMode GetEncapsulationMode (void) const;
private:
EmuNetDevice (const EmuNetDevice &);
EmuNetDevice & operator= (const EmuNetDevice &);
virtual void DoDispose (void);
/**
* Call out to a separate process running as suid root in order to get a raw
* socket. We do this to avoid having the entire simulation running as root.
* If this method returns, we'll have a raw socket waiting for us in m_sock.
*/
void CreateSocket (void);
/**
* Figure out where the raw socket creation process lives on the system.
*/
std::string FindCreator (std::string creatorName);
/**
* Spin up the device
*/
void StartDevice (void);
/**
* Tear down the device
*/
void StopDevice (void);
/**
* Loop to read and process packets
*/
void ReadThread (void);
/**
* Method to handle received packets. Synchronized with simulator via ScheduleNow from ReadThread.
*/
void ForwardUp (uint8_t *buf, uint32_t len);
/**
* Adds the necessary headers and trailers to a packet of data in order to
* respect the protocol implemented by the agent.
* \param p packet
* \param protocolNumber protocol number
*/
void AddHeader (Ptr<Packet> p, uint16_t protocolNumber);
/**
* Removes, from a packet of data, all headers and trailers that
* relate to the protocol implemented by the agent
* \param p Packet whose headers need to be processed
* \param param An integer parameter that can be set by the function
* \return Returns true if the packet should be forwarded up the
* protocol stack.
*/
bool ProcessHeader (Ptr<Packet> p, uint16_t& param);
/**
* Start Sending a Packet Down the Wire.
* @param p packet to send
* @returns true if success, false on failure
*/
bool TransmitStart (Ptr<Packet> p);
void NotifyLinkUp (void);
/**
* The Queue which this EmuNetDevice uses as a packet source.
* Management of this Queue has been delegated to the EmuNetDevice
* and it has the responsibility for deletion.
* @see class Queue
* @see class DropTailQueue
*/
Ptr<Queue> m_queue;
/**
* The trace source fired when packets come into the "top" of the device
* at the L3/L2 transition, before being queued for transmission.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_macTxTrace;
/**
* The trace source fired when packets coming into the "top" of the device
* at the L3/L2 transition are dropped before being queued for transmission.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_macTxDropTrace;
/**
* The trace source fired for packets successfully received by the device
* immediately before being forwarded up to higher layers (at the L2/L3
* transition). This is a promiscuous trace.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_macPromiscRxTrace;
/**
* The trace source fired for packets successfully received by the device
* immediately before being forwarded up to higher layers (at the L2/L3
* transition). This is a non-promiscuous trace.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_macRxTrace;
/**
* The trace source fired for packets successfully received by the device
* but which are dropped before being forwarded up to higher layers (at the
* L2/L3 transition).
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_macRxDropTrace;
/**
* The trace source fired when a packet begins the transmission process on
* the medium.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_phyTxBeginTrace;
/**
* The trace source fired when a packet ends the transmission process on
* the medium.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_phyTxEndTrace;
/**
* The trace source fired when the phy layer drops a packet as it tries
* to transmit it.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_phyTxDropTrace;
/**
* The trace source fired when a packet ends the reception process from
* the medium.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_phyRxTrace;
/**
* The trace source fired when a packet begins the reception process from
* the medium.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_phyRxBeginTrace;
/**
* The trace source fired when a packet begins the reception process from
* the medium.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_phyRxEndTrace;
/**
* The trace source fired when the phy layer drops a packet it has received.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_phyRxDropTrace;
/**
* A trace source that emulates a non-promiscuous protocol sniffer connected
* to the device. Unlike your average everyday sniffer, this trace source
* will not fire on PACKET_OTHERHOST events.
*
* On the transmit size, this trace hook will fire after a packet is dequeued
* from the device queue for transmission. In Linux, for example, this would
* correspond to the point just before a device hard_start_xmit where
* dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
* ETH_P_ALL handlers.
*
* On the receive side, this trace hook will fire when a packet is received,
* just before the receive callback is executed. In Linux, for example,
* this would correspond to the point at which the packet is dispatched to
* packet sniffers in netif_receive_skb.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_snifferTrace;
/**
* A trace source that emulates a promiscuous mode protocol sniffer connected
* to the device. This trace source fire on packets destined for any host
* just like your average everyday packet sniffer.
*
* On the transmit size, this trace hook will fire after a packet is dequeued
* from the device queue for transmission. In Linux, for example, this would
* correspond to the point just before a device hard_start_xmit where
* dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
* ETH_P_ALL handlers.
*
* On the receive side, this trace hook will fire when a packet is received,
* just before the receive callback is executed. In Linux, for example,
* this would correspond to the point at which the packet is dispatched to
* packet sniffers in netif_receive_skb.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_promiscSnifferTrace;
/**
* Time to start spinning up the device
*/
Time m_tStart;
/**
* Time to start tearing down the device
*/
Time m_tStop;
EventId m_startEvent;
EventId m_stopEvent;
int32_t m_sock;
Ptr<SystemThread> m_readThread;
/**
* The Node to which this device is attached.
*/
Ptr<Node> m_node;
/**
* The MAC address which has been assigned to this device.
*/
Mac48Address m_address;
/**
* The callback used to notify higher layers that a packet has been received.
*/
NetDevice::ReceiveCallback m_rxCallback;
/**
* The callback used to notify higher layers that a packet has been received in promiscuous mode.
*/
NetDevice::PromiscReceiveCallback m_promiscRxCallback;
/**
* The ns-3 interface index (in the sense of net device index) that has been assigned to this network device.
*/
uint32_t m_ifIndex;
/**
* The Unix interface index that we got from the system and which corresponds to the interface (e.g., "eth1")
* we are using to talk to the network. Valid when m_sock is valid.
*/
int32_t m_sll_ifindex;
/**
* The type of packet that should be created by the AddHeader
* function and that should be processed by the ProcessHeader
* function.
*/
EncapsulationMode m_encapMode;
/**
* Flag indicating whether or not the link is up. In this case,
* whether or not the device is connected to a channel.
*/
bool m_linkUp;
/**
* Flag indicating whether or not the underlying net device supports
* broadcast.
*/
bool m_isBroadcast;
/**
* Flag indicating whether or not the underlying net device supports
* multicast.
*/
bool m_isMulticast;
/**
* Callbacks to fire if the link changes state (up or down).
*/
TracedCallback<> m_linkChangeCallbacks;
/**
* The unix/linux name of the underlying device (e.g., eth0)
*/
std::string m_deviceName;
/**
* A 64K buffer to hold packet data while it is being sent.
*/
uint8_t *m_packetBuffer;
/*
* a copy of the node id so the read thread doesn't have to GetNode() in
* in order to find the node ID. Thread unsafe reference counting in
* multithreaded apps is not a good thing.
*/
uint32_t m_nodeId;
uint32_t m_maxPendingReads;
uint32_t m_pendingReadCount;
SystemMutex m_pendingReadMutex;
};
} // namespace ns3
#endif /* EMU_NET_DEVICE_H */