23 #include "ns3/queue.h"
24 #include "ns3/simulator.h"
25 #include "ns3/ethernet-header.h"
26 #include "ns3/ethernet-trailer.h"
27 #include "ns3/llc-snap-header.h"
28 #include "ns3/boolean.h"
29 #include "ns3/uinteger.h"
30 #include "ns3/pointer.h"
31 #include "ns3/string.h"
32 #include "ns3/trace-source-accessor.h"
33 #include "ns3/channel.h"
34 #include "ns3/system-thread.h"
35 #include "ns3/mac48-address.h"
40 #include <sys/socket.h>
42 #include <sys/ioctl.h>
43 #include <net/ethernet.h>
45 #include <netinet/in.h>
46 #include <netpacket/packet.h>
47 #include <arpa/inet.h>
60 #define EMU_MAGIC 65867
67 .AddConstructor<EmuNetDevice> ()
68 .AddAttribute (
"Mtu",
"The MAC-level Maximum Transmission Unit",
71 MakeUintegerChecker<uint16_t> ())
72 .AddAttribute (
"Address",
73 "The ns-3 MAC address of this (virtual) device.",
76 MakeMac48AddressChecker ())
77 .AddAttribute (
"DeviceName",
78 "The name of the underlying real device (e.g. eth1).",
82 .AddAttribute (
"Start",
83 "The simulation time at which to spin up the device thread.",
87 .AddAttribute (
"Stop",
88 "The simulation time at which to tear down the device thread.",
92 .AddAttribute (
"EncapsulationMode",
93 "The link-layer encapsulation type to use.",
105 .AddAttribute (
"TxQueue",
106 "A queue to use as the transmit queue in the device.",
109 MakePointerChecker<Queue> ())
111 .AddAttribute (
"RxQueueSize",
"Maximum size of the read queue. "
112 "This value limits number of packets that have been read "
113 "from the network into a memory buffer but have not yet "
114 "been processed by the simulator.",
117 MakeUintegerChecker<uint32_t> ())
127 .AddTraceSource (
"MacTx",
128 "Trace source indicating a packet has arrived for transmission by this device",
130 .AddTraceSource (
"MacTxDrop",
131 "Trace source indicating a packet has been dropped by the device before transmission",
133 .AddTraceSource (
"MacPromiscRx",
134 "A packet has been received by this device, has been passed up from the physical layer "
135 "and is being forwarded up the local protocol stack. This is a promiscuous trace,",
137 .AddTraceSource (
"MacRx",
138 "A packet has been received by this device, has been passed up from the physical layer "
139 "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,",
143 .AddTraceSource (
"MacRxDrop",
144 "Trace source indicating a packet was dropped before being forwarded up the stack",
156 .AddTraceSource (
"PhyTxBegin",
157 "Trace source indicating a packet has begun transmitting over the channel",
159 .AddTraceSource (
"PhyTxEnd",
160 "Trace source indicating a packet has been completely transmitted over the channel",
162 .AddTraceSource (
"PhyTxDrop",
163 "Trace source indicating a packet has been dropped by the device during transmission",
165 .AddTraceSource (
"PhyRxBegin",
166 "Trace source indicating a packet has begun being received by the device",
168 .AddTraceSource (
"PhyRxEnd",
169 "Trace source indicating a packet has been completely received by the device",
171 .AddTraceSource (
"PhyRxDrop",
172 "Trace source indicating a packet has been dropped by the device during reception",
178 .AddTraceSource (
"Sniffer",
179 "Trace source simulating a non-promiscuous packet sniffer attached to the device",
181 .AddTraceSource (
"PromiscSniffer",
182 "Trace source simulating a promiscuous packet sniffer attached to the device",
194 m_ifIndex (std::numeric_limits<uint32_t>::max ()),
196 m_isBroadcast (true),
197 m_isMulticast (false),
198 m_pendingReadCount (0)
271 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Device is already started");
295 bzero (&ifr,
sizeof(ifr));
296 strncpy ((
char *)ifr.ifr_name,
m_deviceName.c_str (), IFNAMSIZ);
299 int32_t rc = ioctl (
m_sock, SIOCGIFINDEX, &ifr);
302 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't get interface index");
313 struct sockaddr_ll ll;
314 bzero (&ll,
sizeof(ll));
316 ll.sll_family = AF_PACKET;
318 ll.sll_protocol = htons (ETH_P_ALL);
322 rc = bind (
m_sock, (
struct sockaddr *)&ll,
sizeof (ll));
325 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't bind to specified interface");
328 rc = ioctl (
m_sock, SIOCGIFFLAGS, &ifr);
331 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't get interface flags");
345 if ((ifr.ifr_flags & IFF_PROMISC) == 0)
349 if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
357 if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
368 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Receive thread is already running");
392 int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
395 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Unix socket creation error, errno = " << std::strerror (errno));
401 struct sockaddr_un un;
402 memset (&un, 0,
sizeof (un));
403 un.sun_family = AF_UNIX;
404 int status = bind (sock, (
struct sockaddr*)&un,
sizeof (sa_family_t));
407 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Could not bind(): errno = " << std::strerror (errno));
420 socklen_t len =
sizeof (un);
421 status = getsockname (sock, (
struct sockaddr*)&un, &len);
424 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Could not getsockname(): errno = " << std::strerror (errno));
431 NS_LOG_INFO (
"Encoded Unix socket as \"" << path <<
"\"");
443 pid_t pid = ::fork ();
453 std::ostringstream oss;
455 NS_LOG_INFO (
"Parameters set to \"" << oss.str () <<
"\"");
460 status = ::execlp (EMU_SOCK_CREATOR,
469 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Back from execlp(), errno = " << std::strerror (errno));
479 pid_t waited = waitpid (pid, &st, 0);
482 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): waitpid() fails, errno = " << std::strerror (errno));
484 NS_ASSERT_MSG (pid == waited,
"EmuNetDevice::CreateSocket(): pid mismatch");
493 int exitStatus = WEXITSTATUS (st);
496 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): socket creator exited normally with status " << exitStatus);
501 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): socket creator exited abnormally");
517 iov.iov_base = &magic;
518 iov.iov_len =
sizeof(magic);
531 size_t msg_size =
sizeof(int);
532 char control[CMSG_SPACE (msg_size)];
549 msg.msg_control = control;
550 msg.msg_controllen =
sizeof (control);
557 ssize_t bytesRead = recvmsg (sock, &msg, 0);
558 if (bytesRead !=
sizeof(
int))
560 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Wrong byte count from socket creator");
568 struct cmsghdr *cmsg;
569 for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
571 if (cmsg->cmsg_level == SOL_SOCKET &&
572 cmsg->cmsg_type == SCM_RIGHTS)
581 NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
582 int *rawSocket = (
int*)CMSG_DATA (cmsg);
583 NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
589 NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
593 NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
620 Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
753 struct sockaddr_ll addr;
754 socklen_t addrSize =
sizeof (addr);
778 struct timespec time = { 0, 100000000L };
779 nanosleep (&time, NULL);
787 uint32_t bufferSize = 65536;
788 uint8_t *buf = (uint8_t *)std::malloc (bufferSize);
791 NS_FATAL_ERROR (
"EmuNetDevice::ReadThread(): malloc packet buffer failed");
795 len = recvfrom (
m_sock, buf, bufferSize, 0, (
struct sockaddr *)&addr, &addrSize);
805 NS_LOG_INFO (
"EmuNetDevice::ReadThread(): Scheduling handler");
896 NS_ASSERT_MSG (packet,
"EmuNetDevice::SendFrom(): packet zero from queue");
901 struct sockaddr_ll ll;
902 bzero (&ll,
sizeof (ll));
904 ll.sll_family = AF_PACKET;
906 ll.sll_protocol = htons (ETH_P_ALL);
916 return rc == -1 ?
false :
true;
991 bzero (&ifr,
sizeof (ifr));
994 int32_t fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_IP);
997 int32_t rc = ioctl (fd, SIOCGIFMTU, &ifr);
1000 NS_FATAL_ERROR (
"EmuNetDevice::GetMtu(): Can't ioctl SIOCGIFMTU");
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Simulation virtual time values and global simulation resolution.
void StopDevice(void)
Tear down the device.
virtual ~EmuNetDevice()
Destroy a EmuNetDevice.
TracedCallback< Ptr< const Packet > > m_macPromiscRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Ptr< const AttributeChecker > MakeEnumChecker(int v1, std::string n1, int v2, std::string n2, int v3, std::string n3, int v4, std::string n4, int v5, std::string n5, int v6, std::string n6, int v7, std::string n7, int v8, std::string n8, int v9, std::string n9, int v10, std::string n10, int v11, std::string n11, int v12, std::string n12, int v13, std::string n13, int v14, std::string n14, int v15, std::string n15, int v16, std::string n16, int v17, std::string n17, int v18, std::string n18, int v19, std::string n19, int v20, std::string n20, int v21, std::string n21, int v22, std::string n22)
SystemMutex m_pendingReadMutex
virtual bool NeedsArp(void) const
Ptr< Queue > m_queue
The Queue which this EmuNetDevice uses as a packet source.
TracedCallback< Ptr< const Packet > > m_promiscSnifferTrace
A trace source that emulates a promiscuous mode protocol sniffer connected to the device...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
std::string EmuBufferToString(uint8_t *buffer, uint32_t len)
Convert a byte buffer to a string containing a hex representation of the buffer.
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
hold variables of type string
std::string m_deviceName
The unix/linux name of the underlying device (e.g., eth0)
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
uint8_t * m_packetBuffer
A 64K buffer to hold packet data while it is being sent.
virtual bool IsBroadcast(void) const
EncapsulationMode
Enumeration of the types of packets supported in the class.
uint64_t GetUid(void) const
Returns the packet's Uid.
bool IsNull(void) const
Check for null implementation.
virtual bool SupportsSendFrom(void) const
bool m_isBroadcast
Flag indicating whether or not the underlying net device supports broadcast.
Ptr< Queue > GetQueue(void) const
Get a copy of the attached Queue.
void StartDevice(void)
Spin up the device.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
TracedCallback< Ptr< const Packet > > m_snifferTrace
A trace source that emulates a non-promiscuous protocol sniffer connected to the device.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
bool IsBroadcast(void) const
virtual void SetNode(Ptr< Node > node)
TracedCallback< Ptr< const Packet > > m_phyTxDropTrace
The trace source fired when the phy layer drops a packet as it tries to transmit it.
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_FATAL_ERROR(msg)
fatal error handling
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
void ReadThread(void)
Loop to read and process packets.
TracedCallback< Ptr< const Packet > > m_macRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
virtual void SetIfIndex(const uint32_t index)
NetDevice::PromiscReceiveCallback m_promiscRxCallback
The callback used to notify higher layers that a packet has been received in promiscuous mode...
TracedCallback< Ptr< const Packet > > m_phyTxBeginTrace
The trace source fired when a packet begins the transmission process on the medium.
TracedCallback< Ptr< const Packet > > m_macTxDropTrace
The trace source fired when packets coming into the "top" of the device at the L3/L2 transition are d...
Ptr< Node > m_node
The Node to which this device is attached.
void Start(Time tStart)
Set a start time for the device.
static TypeId GetTypeId(void)
a polymophic address class
virtual uint32_t GetIfIndex(void) const
virtual Address GetAddress(void) const
Class for representing data rates.
TracedCallback< Ptr< const Packet > > m_phyRxBeginTrace
The trace source fired when a packet begins the reception process from the medium.
bool m_linkUp
Flag indicating whether or not the link is up.
void SetQueue(Ptr< Queue > queue)
Attach a queue to the EmuNetDevice.
hold variables of type 'enum'
static Mac48Address GetMulticast(Ipv4Address address)
hold objects of type ns3::Time
virtual uint16_t GetMtu(void) const
A class which provides a simple way to implement a Critical Section.
virtual Ptr< Node > GetNode(void) const
TracedCallback< Ptr< const Packet > > m_macRxDropTrace
The trace source fired for packets successfully received by the device but which are dropped before b...
Hold an unsigned integer type.
virtual Ptr< Channel > GetChannel(void) const
Ptr< SystemThread > m_readThread
EmuNetDevice::EncapsulationMode GetEncapsulationMode(void) const
Get the encapsulation mode of this device.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
EmuNetDevice()
Construct a EmuNetDevice.
void SetEncapsulationMode(EmuNetDevice::EncapsulationMode mode)
Set the encapsulation mode of this device.
void Stop(Time tStop)
Set a stop time for the device.
static void ScheduleWithContext(uint32_t context, Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event with the given context.
NetDevice::ReceiveCallback m_rxCallback
The callback used to notify higher layers that a packet has been received.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
static Mac48Address ConvertFrom(const Address &address)
virtual void SetPromiscReceiveCallback(PromiscReceiveCallback cb)
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
uint32_t m_ifIndex
The ns-3 interface index (in the sense of net device index) that has been assigned to this network de...
TracedCallback m_linkChangeCallbacks
Callbacks to fire if the link changes state (up or down).
TracedCallback< Ptr< const Packet > > m_phyTxEndTrace
The trace source fired when a packet ends the transmission process on the medium. ...
void ForwardUp(uint8_t *buf, uint32_t len)
Method to handle received packets.
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
virtual bool IsPointToPoint(void) const
Is this a point to point link?
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
bool m_isMulticast
Flag indicating whether or not the underlying net device supports multicast.
virtual void SetAddress(Address address)
Set the address of this interface.
virtual bool IsLinkUp(void) const
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
void SetDataRate(DataRate bps)
Set the Data Rate used for transmission of packets.
TracedCallback< Ptr< const Packet > > m_phyRxEndTrace
The trace source fired when a packet begins the reception process from the medium.
uint32_t m_pendingReadCount
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Describes an IPv6 address.
Ipv4 addresses are stored in host order in this class.
void ConnectWithoutContext(const CallbackBase &callback)
uint32_t GetId(void) const
Time m_tStart
Time to start spinning up the device.
int32_t m_sll_ifindex
The Unix interface index that we got from the system and which corresponds to the interface (e...
TracedCallback< Ptr< const Packet > > m_macTxTrace
The trace source fired when packets come into the "top" of the device at the L3/L2 transition...
uint32_t m_maxPendingReads
Time m_tStop
Time to start tearing down the device.
Network layer to device interface.
hold objects of type ns3::Mac48Address
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
void CreateSocket(void)
Call out to a separate process running as suid root in order to get a raw socket. ...
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Make and return a MAC multicast address using the provided multicast group.
EventImpl * MakeEvent(void(*f)(void))
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
DIX II / Ethernet II packet.
virtual void AddLinkChangeCallback(Callback< void > callback)
PacketType
Packet types are used as they are in Linux.
EncapsulationMode m_encapMode
The type of packet that should be created by the AddHeader function and that should be processed by t...
virtual bool SetMtu(const uint16_t mtu)
a unique identifier for an interface.
virtual Address GetBroadcast(void) const
TypeId SetParent(TypeId tid)
virtual bool IsMulticast(void) const
void AddHeader(const Header &header)
Add header to this packet.
virtual bool IsBridge(void) const
Is this a bridge?
Mac48Address m_address
The MAC address which has been assigned to this device.
TracedCallback< Ptr< const Packet > > m_phyRxDropTrace
The trace source fired when the phy layer drops a packet it has received.