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.",
98 MakeIpv4AddressChecker ())
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.",
104 MakeIpv4AddressChecker ())
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.",
110 MakeMac48AddressChecker ())
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.",
116 MakeIpv4MaskChecker ())
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.
static bool IsMatchingType(const Address &address)
virtual Ptr< Channel > GetChannel(void) const
virtual void DoDispose(void)
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.
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)
Packet addressed to someone else.
void SetBridgedNetDevice(Ptr< NetDevice > bridgedDevice)
Set the ns-3 net device to bridge.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
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
ns-3 uses a pre-created tap, without configuring it
uint64_t GetUid(void) const
Returns the packet's Uid.
void StartTapDevice(void)
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.
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)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_FATAL_ERROR(msg)
fatal error handling
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.
static TypeId GetTypeId(void)
a polymophic address class
virtual bool IsPointToPoint(void) const
Return true if the net device is on a point-to-point link.
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)
hold objects of type ns3::Time
int m_fd
The file descriptor to read from.
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
Hold an unsigned integer type.
Ptr< NetDevice > GetBridgedNetDevice(void)
Get the bridged net device.
Mode
Enumeration of the operating modes supported in the class.
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)
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
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
Ptr< NetDevice > m_bridgedDevice
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)
ns-3 creates and configures tap device
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
Ptr< TapBridgeFdReader > m_fdReader
ns-3 uses a pre-created tap, and bridges to a bridging net device
NetDevice::PromiscReceiveCallback m_promiscRxCallback
bool m_ns3AddressRewritten
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
virtual void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
virtual Address GetAddress(void) const
hold objects of type ns3::Ipv4Address
virtual Address GetBroadcast(void) const
void CopyFrom(const uint8_t buffer[6])
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Describes an IPv6 address.
Ptr< Packet > Filter(Ptr< Packet > packet, Address *src, Address *dst, uint16_t *type)
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)
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if cond is true.
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.
hold objects of type ns3::Mac48Address
bool IsEqual(Ipv4Mask other) const
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
hold objects of type ns3::Ipv4Mask
virtual uint32_t GetIfIndex(void) const
EventImpl * MakeEvent(void(*f)(void))
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
PacketType
Packet types are used as they are in Linux.
virtual bool IsBroadcast(void) const
Ptr< T > GetObject(void) const
void ForwardToBridgedDevice(uint8_t *buf, ssize_t len)
a unique identifier for an interface.
NetDevice::ReceiveCallback m_rxCallback
TypeId SetParent(TypeId tid)
void AddHeader(const Header &header)
Add header to this packet.
virtual bool SupportsSendFrom() const