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(), errno = " << ::strerror (errno));
521 pid_t waited = waitpid (pid, &st, 0);
522 NS_ABORT_MSG_IF (waited == -1,
"TapBridge::CreateTap(): waitpid() fails, errno = " << std::strerror (errno));
523 NS_ASSERT_MSG (pid == waited,
"TapBridge::CreateTap(): pid mismatch");
532 int exitStatus = WEXITSTATUS (st);
534 "TapBridge::CreateTap(): socket creator exited normally with status " << exitStatus);
538 NS_FATAL_ERROR (
"TapBridge::CreateTap(): socket creator exited abnormally");
556 iov.iov_base = &magic;
557 iov.iov_len =
sizeof(magic);
570 size_t msg_size =
sizeof(int);
571 char control[CMSG_SPACE (msg_size)];
588 msg.msg_control = control;
589 msg.msg_controllen =
sizeof (control);
596 ssize_t bytesRead = recvmsg (sock, &msg, 0);
597 NS_ABORT_MSG_IF (bytesRead !=
sizeof(
int),
"TapBridge::CreateTap(): Wrong byte count from socket creator");
604 struct cmsghdr *cmsg;
605 for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
607 if (cmsg->cmsg_level == SOL_SOCKET &&
608 cmsg->cmsg_type == SCM_RIGHTS)
617 NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
618 int *rawSocket = (
int*)CMSG_DATA (cmsg);
619 NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
625 NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
631 NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
644 int ioctlResult = ioctl (sock, SIOCGIFHWADDR, &s);
645 if (ioctlResult == 0)
648 learnedMac.
CopyFrom ((uint8_t *)s.ifr_hwaddr.sa_data);
649 NS_LOG_INFO (
"Learned Tap device MacAddr is " << learnedMac <<
": setting ns-3 device to use this address");
656 NS_LOG_INFO (
"Cannot get MacAddr of Tap device: " <<
m_tapDeviceName <<
" while in USE_LOCAL/USE_BRIDGE mode: " << std::strerror (errno));
657 NS_LOG_INFO (
"Underlying ns-3 device will continue to use default address, what can lead to connectivity errors");
686 NS_LOG_INFO (
"TapBridge::ReadCallback(): Scheduling handler");
722 Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
740 NS_LOG_LOGIC (
"TapBridge::ForwardToBridgedDevice: Discarding packet as unfit for ns-3 consumption");
753 "TapBridge::ForwardToBridgedDevice: Source addr is broadcast");
761 NS_LOG_LOGIC (
"Learned MacAddr is " << learnedMac <<
": setting ns-3 device to use this address");
770 NS_LOG_LOGIC (
"Forwarding packet to ns-3 device via Send()");
891 NS_ASSERT_MSG (
m_node != 0,
"TapBridge::SetBridgedDevice: Bridge not installed in a node");
892 NS_ASSERT_MSG (bridgedDevice !=
this,
"TapBridge::SetBridgedDevice: Cannot bridge to self");
897 NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support eui 48 addresses: cannot be added to bridge.");
902 NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support SendFrom: cannot be added to bridge.");
923 NS_LOG_LOGIC (
"Discarding packet stolen from bridged device " << device);
936 NS_LOG_FUNCTION (device << packet << protocol << src << dst << packetType);
1141 NS_FATAL_ERROR (
"TapBridge::Send: You may not call Send on a TapBridge directly");
1149 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.
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
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
virtual void DoDispose(void)
Destructor implementation.
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)
Fatal error handling.
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...
#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)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
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)
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)
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.
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)
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.
static void ScheduleWithContext(uint32_t context, Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event with the given context.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
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])
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
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.
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.
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< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
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)
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)
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.