23 #include "ns3/channel.h" 
   24 #include "ns3/packet.h" 
   25 #include "ns3/ethernet-header.h" 
   26 #include "ns3/llc-snap-header.h" 
   28 #include "ns3/abort.h" 
   29 #include "ns3/boolean.h" 
   30 #include "ns3/string.h" 
   33 #include "ns3/simulator.h" 
   34 #include "ns3/realtime-simulator-impl.h" 
   35 #include "ns3/unix-fd-reader.h" 
   36 #include "ns3/uinteger.h" 
   40 #include <sys/socket.h> 
   42 #include <sys/ioctl.h> 
   57   uint32_t bufferSize = 65536;
 
   58   uint8_t *buf = (uint8_t *)std::malloc (bufferSize);
 
   62   ssize_t len = read (
m_fd, buf, bufferSize);
 
   74 #define TAP_MAGIC 95549 
   83     .SetGroupName (
"TapBridge")
 
   85     .AddAttribute (
"Mtu", 
"The MAC-level Maximum Transmission Unit",
 
   89                    MakeUintegerChecker<uint16_t> ())
 
   90     .AddAttribute (
"DeviceName", 
 
   91                    "The name of the tap device to create.",
 
   95     .AddAttribute (
"Gateway", 
 
   96                    "The IP address of the default gateway to assign to the host machine, when in ConfigureLocal mode.",
 
  100     .AddAttribute (
"IpAddress", 
 
  101                    "The IP address to assign to the tap device, when in ConfigureLocal mode.  " 
  102                    "This address will override the discovered IP address of the simulated device.",
 
  106     .AddAttribute (
"MacAddress", 
 
  107                    "The MAC address to assign to the tap device, when in ConfigureLocal mode.  " 
  108                    "This address will override the discovered MAC address of the simulated device.",
 
  112     .AddAttribute (
"Netmask", 
 
  113                    "The network mask to assign to the tap device, when in ConfigureLocal mode.  " 
  114                    "This address will override the discovered MAC address of the simulated device.",
 
  118     .AddAttribute (
"Start", 
 
  119                    "The simulation time at which to spin up the tap device read thread.",
 
  123     .AddAttribute (
"Stop", 
 
  124                    "The simulation time at which to tear down the tap device read thread.",
 
  128     .AddAttribute (
"Mode", 
 
  129                    "The operating and configuration mode to use.",
 
  146     m_ns3AddressRewritten (false)
 
  310   int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
 
  311   NS_ABORT_MSG_IF (sock == -1, 
"TapBridge::CreateTap(): Unix socket creation error, errno = " << std::strerror (errno));
 
  316   struct sockaddr_un un;
 
  317   memset (&un, 0, 
sizeof (un));
 
  318   un.sun_family = AF_UNIX;
 
  319   int status = bind (sock, (
struct sockaddr*)&un, 
sizeof (sa_family_t));
 
  320   NS_ABORT_MSG_IF (status == -1, 
"TapBridge::CreateTap(): Could not bind(): errno = " << std::strerror (errno));
 
  331   socklen_t len = 
sizeof (un);
 
  332   status = getsockname (sock, (
struct sockaddr*)&un, &len);
 
  333   NS_ABORT_MSG_IF (status == -1, 
"TapBridge::CreateTap(): Could not getsockname(): errno = " << std::strerror (errno));
 
  339   NS_LOG_INFO (
"Encoded Unix socket as \"" << path << 
"\"");
 
  357   pid_t pid = ::fork ();
 
  396           NS_FATAL_ERROR (
"TapBridge::CreateTap(): Tap device IP configuration requested but neither IP address nor IP netmask is provided");
 
  401       Ipv4Mask ipv4Mask (
"255.255.255.255");
 
  405           uint32_t index = ipv4->GetInterfaceForDevice (nd);
 
  406           if (ipv4->GetNAddresses (index) > 1)
 
  408               NS_LOG_WARN (
"Underlying bridged NetDevice has multiple IP addresses; using first one.");
 
  410           ipv4Address = ipv4->GetAddress (index, 0).GetLocal ();
 
  415           ipv4Mask = ipv4->GetAddress (index, 0).GetMask ();
 
  431       std::ostringstream ossDeviceName;
 
  438       std::ostringstream ossGateway;
 
  446       std::ostringstream ossIp;
 
  449           ossIp << 
"-i" << ipv4Address;
 
  456       std::ostringstream ossMac;
 
  459           ossMac << 
"-m" << mac48Address;
 
  466       std::ostringstream ossNetmask;
 
  469           ossNetmask << 
"-n" << ipv4Mask;
 
  476       std::ostringstream ossMode;
 
  491       std::ostringstream ossPath;
 
  492       ossPath << 
"-p" << path;
 
  496       status = ::execlp (TAP_CREATOR, 
 
  498                          ossDeviceName.str ().c_str (),       
 
  499                          ossGateway.str ().c_str (),          
 
  500                          ossIp.str ().c_str (),               
 
  501                          ossMac.str ().c_str (),              
 
  502                          ossNetmask.str ().c_str (),          
 
  503                          ossMode.str ().c_str (),             
 
  504                          ossPath.str ().c_str (),             
 
  511       NS_FATAL_ERROR (
"TapBridge::CreateTap(): Back from execlp(), status = " << status <<
 
  512                       " errno = " << ::strerror (errno));
 
  522       pid_t waited = waitpid (pid, &st, 0);
 
  523       NS_ABORT_MSG_IF (waited == -1, 
"TapBridge::CreateTap(): waitpid() fails, errno = " << std::strerror (errno));
 
  524       NS_ASSERT_MSG (pid == waited, 
"TapBridge::CreateTap(): pid mismatch");
 
  533           int exitStatus = WEXITSTATUS (st);
 
  535                            "TapBridge::CreateTap(): socket creator exited normally with status " << exitStatus);
 
  539           NS_FATAL_ERROR (
"TapBridge::CreateTap(): socket creator exited abnormally");
 
  557       iov.iov_base = &magic;
 
  558       iov.iov_len = 
sizeof(magic);
 
  571       size_t msg_size = 
sizeof(int);
 
  572       char control[CMSG_SPACE (msg_size)];
 
  589       msg.msg_control = control;
 
  590       msg.msg_controllen = 
sizeof (control);
 
  597       ssize_t bytesRead = recvmsg (sock, &msg, 0);
 
  598       NS_ABORT_MSG_IF (bytesRead != 
sizeof(
int), 
"TapBridge::CreateTap(): Wrong byte count from socket creator");
 
  605       struct cmsghdr *cmsg;
 
  606       for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
 
  608           if (cmsg->cmsg_level == SOL_SOCKET &&
 
  609               cmsg->cmsg_type == SCM_RIGHTS)
 
  618                   NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
 
  619                   int *rawSocket = (
int*)CMSG_DATA (cmsg);
 
  620                   NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
 
  626                   NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
 
  632           NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
 
  645           int ioctlResult = ioctl (sock, SIOCGIFHWADDR, &s);
 
  646           if (ioctlResult == 0)
 
  649               learnedMac.
CopyFrom ((uint8_t *)s.ifr_hwaddr.sa_data);
 
  650               NS_LOG_INFO (
"Learned Tap device MacAddr is " << learnedMac << 
": setting ns-3 device to use this address");
 
  657               NS_LOG_INFO (
"Cannot get MacAddr of Tap device: " << 
m_tapDeviceName << 
" while in USE_LOCAL/USE_BRIDGE mode: " << std::strerror (errno));
 
  658               NS_LOG_INFO (
"Underlying ns-3 device will continue to use default address, what can lead to connectivity errors");
 
  687   NS_LOG_INFO (
"TapBridge::ReadCallback(): Scheduling handler");
 
  723   Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
 
  741       NS_LOG_LOGIC (
"TapBridge::ForwardToBridgedDevice:  Discarding packet as unfit for ns-3 consumption");
 
  754                      "TapBridge::ForwardToBridgedDevice:  Source addr is broadcast");
 
  762           NS_LOG_LOGIC (
"Learned MacAddr is " << learnedMac << 
": setting ns-3 device to use this address");
 
  771       NS_LOG_LOGIC (
"Forwarding packet to ns-3 device via Send()");
 
  892   NS_ASSERT_MSG (
m_node != 0, 
"TapBridge::SetBridgedDevice:  Bridge not installed in a node");
 
  893   NS_ASSERT_MSG (bridgedDevice != 
this, 
"TapBridge::SetBridgedDevice:  Cannot bridge to self");
 
  898       NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support eui 48 addresses: cannot be added to bridge.");
 
  903       NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support SendFrom: cannot be added to bridge.");
 
  924   NS_LOG_LOGIC (
"Discarding packet stolen from bridged device " << device);
 
  937   NS_LOG_FUNCTION (device << packet << protocol << src << dst << packetType);
 
 1142   NS_FATAL_ERROR (
"TapBridge::Send: You may not call Send on a TapBridge directly");
 
 1150   NS_FATAL_ERROR (
"TapBridge::Send: You may not call SendFrom on a TapBridge directly");
 
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer. 
 
Time m_tStop
Time to start tearing down the device. 
 
Ptr< const AttributeChecker > MakeStringChecker(void)
 
static bool IsMatchingType(const Address &address)
 
EventId m_startEvent
The ID of the ns-3 event used to schedule the start up of the underlying host Tap device and ns-3 rea...
 
virtual Ptr< Channel > GetChannel(void) const 
 
Ipv4Address m_tapIp
The IP address to use as the device IP on the host. 
 
virtual void DoDispose(void)
Call out to a separate process running as suid root in order to get our tap device created...
 
static Ipv4Mask GetOnes(void)
 
Simulation virtual time values and global simulation resolution. 
 
virtual void SetNode(Ptr< Node > node)
 
virtual Ptr< Node > GetNode(void) const 
 
A structure representing data read. 
 
Smart pointer class similar to boost::intrusive_ptr. 
 
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
 
virtual Address GetMulticast(Ipv4Address multicastGroup) const 
Make and return a MAC multicast address using the provided multicast group. 
 
Mode m_mode
The operating mode of the bridge. 
 
Ptr< const AttributeAccessor > MakeIpv4MaskAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
 
void SetBridgedNetDevice(Ptr< NetDevice > bridgedDevice)
Set the ns-3 net device to bridge. 
 
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system. 
 
void SetMode(TapBridge::Mode mode)
Set the operating mode of this device. 
 
Ptr< T > GetObject(void) const 
Get a pointer to the requested aggregated Object. 
 
Hold variables of type string. 
 
virtual bool SetMtu(const uint16_t mtu)
 
a class to represent an Ipv4 address mask 
 
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
 
uint64_t GetUid(void) const 
Returns the packet's Uid. 
 
ns-3 creates and configures tap device 
 
uint32_t m_nodeId
a copy of the node id so the read thread doesn't have to GetNode() in in order to find the node ID...
 
void StartTapDevice(void)
Spin up the device. 
 
PacketType
Packet types are used as they are in Linux. 
 
void Start(Time tStart)
Set a start time for the device. 
 
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name. 
 
EventId m_stopEvent
The ID of the ns-3 event used to schedule the tear down of the underlying host Tap device and ns-3 re...
 
uint32_t GetSize(void) const 
Returns the the size in bytes of the packet (including the zero-filled initial payload). 
 
bool IsBroadcast(void) const 
 
ns-3 uses a pre-created tap, and bridges to a bridging net device 
 
Mac48Address m_tapMac
The MAC address to use as the hardware address on the host; only used in UseLocal mode...
 
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO. 
 
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate. 
 
Ptr< const AttributeChecker > MakeMac48AddressChecker(void)
 
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...
 
virtual void DoDispose(void)
Destructor implementation. 
 
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function. 
 
bool DiscardFromBridgedDevice(Ptr< NetDevice > device, Ptr< const Packet > packet, uint16_t protocol, Address const &src)
Receives a packet from a bridged Device. 
 
void Stop(Time tStop)
Set a stop time for the device. 
 
Ptr< const AttributeAccessor > MakeMac48AddressAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
 
static TypeId GetTypeId(void)
Get the type ID. 
 
a polymophic address class 
 
bool m_linkUp
Flag indicating whether or not the link is up. 
 
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range. 
 
virtual bool IsPointToPoint(void) const 
Return true if the net device is on a point-to-point link. 
 
void CreateTap(void)
Call out to a separate process running as suid root in order to get our tap device created...
 
std::string TapBufferToString(uint8_t *buffer, uint32_t len)
Convert a byte buffer to a string containing a hex representation of the buffer. 
 
uint8_t * m_packetBuffer
A 64K buffer to hold packet data while it is being sent. 
 
virtual void AddLinkChangeCallback(Callback< void > callback)
 
NS_ASSERT_MSG(false,"Ipv4AddressGenerator::MaskToIndex(): Impossible")
 
virtual void SetIfIndex(const uint32_t index)
 
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet. 
 
Hold variables of type enum. 
 
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay. 
 
virtual bool IsBridge(void) const 
Return true if the net device is acting as a bridge. 
 
static Mac48Address GetMulticast(Ipv4Address address)
 
AttributeValue implementation for Time. 
 
int m_fd
The file descriptor to read from. 
 
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
 
Ptr< const AttributeChecker > MakeIpv4AddressChecker(void)
 
Hold an unsigned integer type. 
 
A bridge to make it appear that a real host process is connected to an ns-3 net device. 
 
Ptr< NetDevice > GetBridgedNetDevice(void)
Get the bridged net device. 
 
bool IsBroadcast(void) const 
 
FdReader::Data DoRead(void)
The read implementation. 
 
bool ReceiveFromBridgedDevice(Ptr< NetDevice > device, Ptr< const Packet > packet, uint16_t protocol, Address const &src, Address const &dst, PacketType packetType)
Receives a packet from a bridged Device. 
 
uint32_t m_ifIndex
The ns-3 interface index of this TapBridge net device. 
 
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
 
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
 
virtual uint16_t GetMtu(void) const 
 
virtual bool NeedsArp(void) const 
 
void StopTapDevice(void)
Tear down the device. 
 
TracedCallback m_linkChangeCallbacks
Callbacks to fire if the link changes state (up or down). 
 
Ptr< NetDevice > m_bridgedDevice
The ns-3 net device to which we are bridging. 
 
virtual void SetAddress(Address address)
Set the address of this interface. 
 
static Mac48Address ConvertFrom(const Address &address)
 
void ReadCallback(uint8_t *buf, ssize_t len)
Callback to process packets that are read. 
 
Access to the IPv4 forwarding table, interfaces, and configuration. 
 
Ptr< Packet > Copy(void) const 
performs a COW copy of the packet. 
 
uint32_t PeekHeader(Header &header) const 
Deserialize but does not remove the header from the internal buffer. 
 
std::string m_tapDeviceName
The name of the device to create on the host. 
 
Every class exported by the ns3 library is enclosed in the ns3 namespace. 
 
Ptr< Node > m_node
Pointer to the (ghost) Node to which we are connected. 
 
Ptr< TapBridgeFdReader > m_fdReader
Includes the ns-3 read thread used to do blocking reads on the fd corresponding to the host device...
 
Packet addressed to someone else. 
 
Time m_tStart
Time to start spinning up the device. 
 
NetDevice::PromiscReceiveCallback m_promiscRxCallback
Callback used to hook the promiscuous packet receive callback of the TapBridge ns-3 net device...
 
Ipv4Address m_tapGateway
The IP address to use as the device default gateway on the host. 
 
bool m_ns3AddressRewritten
Whether the MAC address of the underlying ns-3 device has already been rewritten is stored in this va...
 
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
 
virtual void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
 
virtual Address GetAddress(void) const 
 
AttributeValue implementation for Ipv4Address. 
 
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
 
virtual Address GetBroadcast(void) const 
 
void CopyFrom(const uint8_t buffer[6])
 
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
 
Mac48Address m_address
The (unused) MAC address of the TapBridge net device. 
 
Mode
Enumeration of the operating modes supported in the class. 
 
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)
Make an EnumChecker pre-configured with a set of allowed values by name. 
 
Describes an IPv6 address. 
 
Ptr< Packet > Filter(Ptr< Packet > packet, Address *src, Address *dst, uint16_t *type)
The host we are bridged to is in the evil real world. 
 
static void ScheduleWithContext(uint32_t context, Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event with the given context. 
 
Ipv4 addresses are stored in host order in this class. 
 
TapBridge::Mode GetMode(void)
Get the operating mode of this device. 
 
virtual bool IsMulticast(void) const 
 
void ConnectWithoutContext(const CallbackBase &callback)
Append a Callback to the chain (without a context). 
 
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message. 
 
uint32_t GetId(void) const 
 
virtual bool IsLinkUp(void) const 
 
Network layer to device interface. 
 
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN. 
 
AttributeValue implementation for Mac48Address. 
 
bool IsEqual(Ipv4Mask other) const 
 
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG. 
 
ns-3 uses a pre-created tap, without configuring it 
 
Time Seconds(double value)
Construct a Time in the indicated unit. 
 
AttributeValue implementation for Ipv4Mask. 
 
Ptr< const AttributeChecker > MakeIpv4MaskChecker(void)
 
Ipv4Mask m_tapNetmask
The network mask to assign to the device created on the host. 
 
void NotifyLinkUp(void)
Notifies that the link is up and ready. 
 
virtual uint32_t GetIfIndex(void) const 
 
uint32_t CopyData(uint8_t *buffer, uint32_t size) const 
Copy the packet contents to a byte buffer. 
 
Ptr< const AttributeAccessor > MakeStringAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
 
Ptr< const AttributeAccessor > MakeIpv4AddressAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
 
virtual bool IsBroadcast(void) const 
 
uint16_t m_mtu
The common mtu to use for the net devices. 
 
int m_sock
The socket (actually interpreted as fd) to use to talk to the Tap device on the real internet host...
 
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
 
void ForwardToBridgedDevice(uint8_t *buf, ssize_t len)
Forward a packet received from the tap device to the bridged ns-3 device. 
 
a unique identifier for an interface. 
 
NetDevice::ReceiveCallback m_rxCallback
Callback used to hook the standard packet receive callback of the TapBridge ns-3 net device...
 
TypeId SetParent(TypeId tid)
Set the parent TypeId. 
 
void AddHeader(const Header &header)
Add header to this packet. 
 
virtual bool SupportsSendFrom() const 
 
EventImpl * MakeEvent(void(*f)(void))
Make an EventImpl from a function pointer taking varying numbers of arguments.