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>
61 #define EMU_MAGIC 65867
68 .AddConstructor<EmuNetDevice> ()
69 .AddAttribute (
"Mtu",
"The MAC-level Maximum Transmission Unit",
72 MakeUintegerChecker<uint16_t> ())
73 .AddAttribute (
"Address",
74 "The ns-3 MAC address of this (virtual) device.",
77 MakeMac48AddressChecker ())
78 .AddAttribute (
"DeviceName",
79 "The name of the underlying real device (e.g. eth1).",
83 .AddAttribute (
"Start",
84 "The simulation time at which to spin up the device thread.",
88 .AddAttribute (
"Stop",
89 "The simulation time at which to tear down the device thread.",
93 .AddAttribute (
"EncapsulationMode",
94 "The link-layer encapsulation type to use.",
106 .AddAttribute (
"TxQueue",
107 "A queue to use as the transmit queue in the device.",
110 MakePointerChecker<Queue> ())
112 .AddAttribute (
"RxQueueSize",
"Maximum size of the read queue. "
113 "This value limits number of packets that have been read "
114 "from the network into a memory buffer but have not yet "
115 "been processed by the simulator.",
118 MakeUintegerChecker<uint32_t> ())
128 .AddTraceSource (
"MacTx",
129 "Trace source indicating a packet has arrived for transmission by this device",
131 .AddTraceSource (
"MacTxDrop",
132 "Trace source indicating a packet has been dropped by the device before transmission",
134 .AddTraceSource (
"MacPromiscRx",
135 "A packet has been received by this device, has been passed up from the physical layer "
136 "and is being forwarded up the local protocol stack. This is a promiscuous trace,",
138 .AddTraceSource (
"MacRx",
139 "A packet has been received by this device, has been passed up from the physical layer "
140 "and is being forwarded up the local protocol stack. This is a non-promiscuous trace,",
144 .AddTraceSource (
"MacRxDrop",
145 "Trace source indicating a packet was dropped before being forwarded up the stack",
157 .AddTraceSource (
"PhyTxBegin",
158 "Trace source indicating a packet has begun transmitting over the channel",
160 .AddTraceSource (
"PhyTxEnd",
161 "Trace source indicating a packet has been completely transmitted over the channel",
163 .AddTraceSource (
"PhyTxDrop",
164 "Trace source indicating a packet has been dropped by the device during transmission",
166 .AddTraceSource (
"PhyRxBegin",
167 "Trace source indicating a packet has begun being received by the device",
169 .AddTraceSource (
"PhyRxEnd",
170 "Trace source indicating a packet has been completely received by the device",
172 .AddTraceSource (
"PhyRxDrop",
173 "Trace source indicating a packet has been dropped by the device during reception",
179 .AddTraceSource (
"Sniffer",
180 "Trace source simulating a non-promiscuous packet sniffer attached to the device",
182 .AddTraceSource (
"PromiscSniffer",
183 "Trace source simulating a promiscuous packet sniffer attached to the device",
195 m_ifIndex (std::numeric_limits<uint32_t>::max ()),
197 m_isBroadcast (true),
198 m_isMulticast (false),
199 m_pendingReadCount (0)
272 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Device is already started");
296 bzero (&ifr,
sizeof(ifr));
297 strncpy ((
char *)ifr.ifr_name,
m_deviceName.c_str (), IFNAMSIZ);
300 int32_t rc = ioctl (
m_sock, SIOCGIFINDEX, &ifr);
303 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't get interface index");
314 struct sockaddr_ll ll;
315 bzero (&ll,
sizeof(ll));
317 ll.sll_family = AF_PACKET;
319 ll.sll_protocol = htons (ETH_P_ALL);
323 rc = bind (
m_sock, (
struct sockaddr *)&ll,
sizeof (ll));
326 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't bind to specified interface");
329 rc = ioctl (
m_sock, SIOCGIFFLAGS, &ifr);
332 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Can't get interface flags");
346 if ((ifr.ifr_flags & IFF_PROMISC) == 0)
350 if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
358 if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
369 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Receive thread is already running");
393 int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
396 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Unix socket creation error, errno = " << std::strerror (errno));
402 struct sockaddr_un un;
403 memset (&un, 0,
sizeof (un));
404 un.sun_family = AF_UNIX;
405 int status = bind (sock, (
struct sockaddr*)&un,
sizeof (sa_family_t));
408 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Could not bind(): errno = " << std::strerror (errno));
421 socklen_t len =
sizeof (un);
422 status = getsockname (sock, (
struct sockaddr*)&un, &len);
425 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Could not getsockname(): errno = " << std::strerror (errno));
432 NS_LOG_INFO (
"Encoded Unix socket as \"" << path <<
"\"");
444 pid_t pid = ::fork ();
454 std::ostringstream oss;
456 NS_LOG_INFO (
"Parameters set to \"" << oss.str () <<
"\"");
461 status = ::execlp (EMU_SOCK_CREATOR,
470 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Back from execlp(), errno = " << std::strerror (errno));
480 pid_t waited = waitpid (pid, &st, 0);
483 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): waitpid() fails, errno = " << std::strerror (errno));
485 NS_ASSERT_MSG (pid == waited,
"EmuNetDevice::CreateSocket(): pid mismatch");
494 int exitStatus = WEXITSTATUS (st);
497 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): socket creator exited normally with status " << exitStatus);
502 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): socket creator exited abnormally");
518 iov.iov_base = &magic;
519 iov.iov_len =
sizeof(magic);
532 size_t msg_size =
sizeof(int);
533 char control[CMSG_SPACE (msg_size)];
550 msg.msg_control = control;
551 msg.msg_controllen =
sizeof (control);
558 ssize_t bytesRead = recvmsg (sock, &msg, 0);
559 if (bytesRead !=
sizeof(
int))
561 NS_FATAL_ERROR (
"EmuNetDevice::CreateSocket(): Wrong byte count from socket creator");
569 struct cmsghdr *cmsg;
570 for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
572 if (cmsg->cmsg_level == SOL_SOCKET &&
573 cmsg->cmsg_type == SCM_RIGHTS)
582 NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
583 int *rawSocket = (
int*)CMSG_DATA (cmsg);
584 NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
590 NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
594 NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
621 Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
754 struct sockaddr_ll addr;
755 socklen_t addrSize =
sizeof (addr);
779 struct timespec time = { 0, 100000000L };
780 nanosleep (&time, NULL);
788 uint32_t bufferSize = 65536;
789 uint8_t *buf = (uint8_t *)std::malloc (bufferSize);
792 NS_FATAL_ERROR (
"EmuNetDevice::ReadThread(): malloc packet buffer failed");
796 len = recvfrom (
m_sock, buf, bufferSize, 0, (
struct sockaddr *)&addr, &addrSize);
806 NS_LOG_INFO (
"EmuNetDevice::ReadThread(): Scheduling handler");
897 NS_ASSERT_MSG (packet,
"EmuNetDevice::SendFrom(): packet zero from queue");
902 struct sockaddr_ll ll;
903 bzero (&ll,
sizeof (ll));
905 ll.sll_family = AF_PACKET;
907 ll.sll_protocol = htons (ETH_P_ALL);
917 return rc == -1 ?
false :
true;
992 bzero (&ifr,
sizeof (ifr));
995 int32_t fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_IP);
998 int32_t rc = ioctl (fd, SIOCGIFMTU, &ifr);
1001 NS_FATAL_ERROR (
"EmuNetDevice::GetMtu(): Can't ioctl SIOCGIFMTU");
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
keep track of time values and allow control of 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)
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...
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
A packet is allocated a new uid when it is created empty or with zero-filled payload.
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.
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
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)
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
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...
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)
#define NS_FATAL_ERROR(msg)
fatal error handling
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)
static Mac48Address ConvertFrom(const Address &address)
virtual void SetPromiscReceiveCallback(PromiscReceiveCallback cb)
Ptr< Packet > Copy(void) const
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?
hold objects of type Ptr<T>
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)
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)
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.