19 #include "emu-net-device.h"
20 #include "emu-encode-decode.h"
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>
58 NS_OBJECT_ENSURE_REGISTERED (EmuNetDevice);
60 #define EMU_MAGIC 65867
63 EmuNetDevice::GetTypeId (
void)
65 static TypeId tid = TypeId (
"ns3::EmuNetDevice")
66 .SetParent<NetDevice> ()
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.",
74 Mac48AddressValue (Mac48Address (
"ff:ff:ff:ff:ff:ff")),
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.",
96 MakeEnumChecker (
DIX,
"Dix",
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.",
115 UintegerValue (1000),
116 MakeUintegerAccessor (&EmuNetDevice::m_maxPendingReads),
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)
215 if (m_readThread != 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)
366 if (m_readThread != 0)
368 NS_FATAL_ERROR (
"EmuNetDevice::StartDevice(): Receive thread is already running");
374 m_readThread->Start ();
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)
579 if (magic == EMU_MAGIC)
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");
605 NS_ASSERT_MSG (m_readThread != 0,
"EmuNetDevice::StopDevice(): Receive thread is not running");
608 m_readThread->Join ();
620 Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
627 --m_pendingReadCount;
680 protocol = llc.GetType ();
701 packetType = NS3_PACKET_BROADCAST;
705 packetType = NS3_PACKET_MULTICAST;
709 packetType = NS3_PACKET_HOST;
713 packetType = NS3_PACKET_OTHERHOST;
734 if (packetType != NS3_PACKET_OTHERHOST)
753 struct sockaddr_ll addr;
754 socklen_t addrSize =
sizeof (addr);
766 if (m_pendingReadCount >= m_maxPendingReads)
772 ++m_pendingReadCount;
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);
804 NS_LOG_INFO (
"EmuNetDevice::EmuNetDevice(): Received packet on node " << m_nodeId);
805 NS_LOG_INFO (
"EmuNetDevice::ReadThread(): Scheduling handler");
867 llc.SetType (protocolNumber);
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);
913 int32_t rc = sendto (m_sock,
m_packetBuffer, packet->
GetSize (), 0,
reinterpret_cast<struct sockaddr *
> (&ll),
sizeof (ll));
916 return rc == -1 ?
false :
true;
941 EmuNetDevice::NotifyLinkUp (
void)
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)
TracedCallback< Ptr< const Packet > > m_macPromiscRxTrace
#define NS_LOG_FUNCTION(parameters)
virtual bool NeedsArp(void) const
TracedCallback< Ptr< const Packet > > m_promiscSnifferTrace
std::string EmuBufferToString(uint8_t *buffer, uint32_t len)
Convert a byte buffer to a string containing a hex representation of the buffer. Make the string pret...
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
virtual bool IsBroadcast(void) const
uint64_t GetUid(void) const
virtual bool SupportsSendFrom(void) const
Ptr< Queue > GetQueue(void) const
#define NS_LOG_COMPONENT_DEFINE(name)
TracedCallback< Ptr< const Packet > > m_snifferTrace
uint32_t GetSize(void) const
bool IsBroadcast(void) const
virtual void SetNode(Ptr< Node > node)
TracedCallback< Ptr< const Packet > > m_phyTxDropTrace
virtual void DoDispose(void)
static void Cancel(const EventId &id)
#define NS_LOG_FUNCTION_NOARGS()
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
TracedCallback< Ptr< const Packet > > m_macRxTrace
virtual void SetIfIndex(const uint32_t index)
NetDevice::PromiscReceiveCallback m_promiscRxCallback
TracedCallback< Ptr< const Packet > > m_phyTxBeginTrace
TracedCallback< Ptr< const Packet > > m_macTxDropTrace
#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
void SetQueue(Ptr< Queue > queue)
static Mac48Address GetMulticast(Ipv4Address address)
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
virtual Ptr< Channel > GetChannel(void) const
EmuNetDevice::EncapsulationMode GetEncapsulationMode(void) const
void SetEncapsulationMode(EmuNetDevice::EncapsulationMode mode)
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
static void ScheduleWithContext(uint32_t context, Time const &time, MEM mem_ptr, OBJ obj)
NetDevice::ReceiveCallback m_rxCallback
#define NS_LOG_LOGIC(msg)
static Mac48Address ConvertFrom(const Address &address)
virtual void SetPromiscReceiveCallback(PromiscReceiveCallback cb)
Ptr< Packet > Copy(void) const
TracedCallback m_linkChangeCallbacks
TracedCallback< Ptr< const Packet > > m_phyTxEndTrace
void ForwardUp(uint8_t *buf, uint32_t len)
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
virtual bool IsPointToPoint(void) const
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
virtual void SetAddress(Address address)
virtual bool IsLinkUp(void) const
void SetDataRate(DataRate bps)
TracedCallback< Ptr< const Packet > > m_phyRxEndTrace
#define NS_ASSERT_MSG(condition, message)
Describes an IPv6 address.
Ipv4 addresses are stored in host order in this class.
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
void ConnectWithoutContext(const CallbackBase &callback)
uint32_t GetId(void) const
TracedCallback< Ptr< const Packet > > m_macTxTrace
#define NS_LOG_DEBUG(msg)
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Make and return a MAC multicast address using the provided multicast group.
virtual void DoDispose(void)
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
virtual void AddLinkChangeCallback(Callback< void > callback)
EncapsulationMode m_encapMode
virtual bool SetMtu(const uint16_t mtu)
virtual Address GetBroadcast(void) const
virtual bool IsMulticast(void) const
void AddHeader(const Header &header)
virtual bool IsBridge(void) const
TracedCallback< Ptr< const Packet > > m_phyRxDropTrace