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