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 .AddConstructor<TapBridge> ()
84 .AddAttribute (
"Mtu",
"The MAC-level Maximum Transmission Unit",
88 MakeUintegerChecker<uint16_t> ())
89 .AddAttribute (
"DeviceName",
90 "The name of the tap device to create.",
94 .AddAttribute (
"Gateway",
95 "The IP address of the default gateway to assign to the host machine, when in ConfigureLocal mode.",
99 .AddAttribute (
"IpAddress",
100 "The IP address to assign to the tap device, when in ConfigureLocal mode. "
101 "This address will override the discovered IP address of the simulated device.",
105 .AddAttribute (
"MacAddress",
106 "The MAC address to assign to the tap device, when in ConfigureLocal mode. "
107 "This address will override the discovered MAC address of the simulated device.",
111 .AddAttribute (
"Netmask",
112 "The network mask to assign to the tap device, when in ConfigureLocal mode. "
113 "This address will override the discovered MAC address of the simulated device.",
117 .AddAttribute (
"Start",
118 "The simulation time at which to spin up the tap device read thread.",
122 .AddAttribute (
"Stop",
123 "The simulation time at which to tear down the tap device read thread.",
127 .AddAttribute (
"Mode",
128 "The operating and configuration mode to use.",
145 m_ns3AddressRewritten (false)
309 int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
310 NS_ABORT_MSG_IF (sock == -1,
"TapBridge::CreateTap(): Unix socket creation error, errno = " << std::strerror (errno));
315 struct sockaddr_un un;
316 memset (&un, 0,
sizeof (un));
317 un.sun_family = AF_UNIX;
318 int status = bind (sock, (
struct sockaddr*)&un,
sizeof (sa_family_t));
319 NS_ABORT_MSG_IF (status == -1,
"TapBridge::CreateTap(): Could not bind(): errno = " << std::strerror (errno));
330 socklen_t len =
sizeof (un);
331 status = getsockname (sock, (
struct sockaddr*)&un, &len);
332 NS_ABORT_MSG_IF (status == -1,
"TapBridge::CreateTap(): Could not getsockname(): errno = " << std::strerror (errno));
338 NS_LOG_INFO (
"Encoded Unix socket as \"" << path <<
"\"");
356 pid_t pid = ::fork ();
395 NS_FATAL_ERROR (
"TapBridge::CreateTap(): Tap device IP configuration requested but neither IP address nor IP netmask is provided");
400 Ipv4Mask ipv4Mask (
"255.255.255.255");
404 uint32_t index = ipv4->GetInterfaceForDevice (nd);
405 if (ipv4->GetNAddresses (index) > 1)
407 NS_LOG_WARN (
"Underlying bridged NetDevice has multiple IP addresses; using first one.");
409 ipv4Address = ipv4->GetAddress (index, 0).GetLocal ();
414 ipv4Mask = ipv4->GetAddress (index, 0).GetMask ();
430 std::ostringstream ossDeviceName;
437 std::ostringstream ossGateway;
445 std::ostringstream ossIp;
448 ossIp <<
"-i" << ipv4Address;
455 std::ostringstream ossMac;
458 ossMac <<
"-m" << mac48Address;
465 std::ostringstream ossNetmask;
468 ossNetmask <<
"-n" << ipv4Mask;
475 std::ostringstream ossMode;
490 std::ostringstream ossPath;
491 ossPath <<
"-p" << path;
495 status = ::execlp (TAP_CREATOR,
497 ossDeviceName.str ().c_str (),
498 ossGateway.str ().c_str (),
499 ossIp.str ().c_str (),
500 ossMac.str ().c_str (),
501 ossNetmask.str ().c_str (),
502 ossMode.str ().c_str (),
503 ossPath.str ().c_str (),
510 NS_FATAL_ERROR (
"TapBridge::CreateTap(): Back from execlp(), errno = " << ::strerror (errno));
520 pid_t waited = waitpid (pid, &st, 0);
521 NS_ABORT_MSG_IF (waited == -1,
"TapBridge::CreateTap(): waitpid() fails, errno = " << std::strerror (errno));
522 NS_ASSERT_MSG (pid == waited,
"TapBridge::CreateTap(): pid mismatch");
531 int exitStatus = WEXITSTATUS (st);
533 "TapBridge::CreateTap(): socket creator exited normally with status " << exitStatus);
537 NS_FATAL_ERROR (
"TapBridge::CreateTap(): socket creator exited abnormally");
555 iov.iov_base = &magic;
556 iov.iov_len =
sizeof(magic);
569 size_t msg_size =
sizeof(int);
570 char control[CMSG_SPACE (msg_size)];
587 msg.msg_control = control;
588 msg.msg_controllen =
sizeof (control);
595 ssize_t bytesRead = recvmsg (sock, &msg, 0);
596 NS_ABORT_MSG_IF (bytesRead !=
sizeof(
int),
"TapBridge::CreateTap(): Wrong byte count from socket creator");
603 struct cmsghdr *cmsg;
604 for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
606 if (cmsg->cmsg_level == SOL_SOCKET &&
607 cmsg->cmsg_type == SCM_RIGHTS)
616 NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
617 int *rawSocket = (
int*)CMSG_DATA (cmsg);
618 NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
624 NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
630 NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
643 int ioctlResult = ioctl (sock, SIOCGIFHWADDR, &s);
644 if (ioctlResult == 0)
647 learnedMac.
CopyFrom ((uint8_t *)s.ifr_hwaddr.sa_data);
648 NS_LOG_INFO (
"Learned Tap device MacAddr is " << learnedMac <<
": setting ns-3 device to use this address");
655 NS_LOG_INFO (
"Cannot get MacAddr of Tap device: " <<
m_tapDeviceName <<
" while in USE_LOCAL/USE_BRIDGE mode: " << std::strerror (errno));
656 NS_LOG_INFO (
"Underlying ns-3 device will continue to use default address, what can lead to connectivity errors");
685 NS_LOG_INFO (
"TapBridge::ReadCallback(): Scheduling handler");
721 Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
739 NS_LOG_LOGIC (
"TapBridge::ForwardToBridgedDevice: Discarding packet as unfit for ns-3 consumption");
752 "TapBridge::ForwardToBridgedDevice: Source addr is broadcast");
760 NS_LOG_LOGIC (
"Learned MacAddr is " << learnedMac <<
": setting ns-3 device to use this address");
769 NS_LOG_LOGIC (
"Forwarding packet to ns-3 device via Send()");
890 NS_ASSERT_MSG (
m_node != 0,
"TapBridge::SetBridgedDevice: Bridge not installed in a node");
891 NS_ASSERT_MSG (bridgedDevice !=
this,
"TapBridge::SetBridgedDevice: Cannot bridge to self");
896 NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support eui 48 addresses: cannot be added to bridge.");
901 NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support SendFrom: cannot be added to bridge.");
922 NS_LOG_LOGIC (
"Discarding packet stolen from bridged device " << device);
935 NS_LOG_FUNCTION (device << packet << protocol << src << dst << packetType);
1140 NS_FATAL_ERROR (
"TapBridge::Send: You may not call Send on a TapBridge directly");
1148 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.
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.