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>
61 #include <linux/if_tun.h>
62 #include <sys/ioctl.h>
73 uint32_t bufferSize = 65536;
74 uint8_t *buf = (uint8_t *)std::malloc (bufferSize);
78 ssize_t len = read (
m_fd, buf, bufferSize);
90 #define TAP_MAGIC 95549
99 .AddConstructor<TapBridge> ()
100 .AddAttribute (
"Mtu",
"The MAC-level Maximum Transmission Unit",
104 MakeUintegerChecker<uint16_t> ())
105 .AddAttribute (
"DeviceName",
106 "The name of the tap device to create.",
109 MakeStringChecker ())
110 .AddAttribute (
"Gateway",
111 "The IP address of the default gateway to assign to the host machine, when in ConfigureLocal mode.",
114 MakeIpv4AddressChecker ())
115 .AddAttribute (
"IpAddress",
116 "The IP address to assign to the tap device, when in ConfigureLocal mode. "
117 "This address will override the discovered IP address of the simulated device.",
120 MakeIpv4AddressChecker ())
121 .AddAttribute (
"MacAddress",
122 "The MAC address to assign to the tap device, when in ConfigureLocal mode. "
123 "This address will override the discovered MAC address of the simulated device.",
126 MakeMac48AddressChecker ())
127 .AddAttribute (
"Netmask",
128 "The network mask to assign to the tap device, when in ConfigureLocal mode. "
129 "This address will override the discovered MAC address of the simulated device.",
132 MakeIpv4MaskChecker ())
133 .AddAttribute (
"Start",
134 "The simulation time at which to spin up the tap device read thread.",
138 .AddAttribute (
"Stop",
139 "The simulation time at which to tear down the tap device read thread.",
143 .AddAttribute (
"Mode",
144 "The operating and configuration mode to use.",
161 m_ns3AddressRewritten (false)
322 int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
323 NS_ABORT_MSG_IF (sock == -1,
"TapBridge::CreateTap(): Unix socket creation error, errno = " << std::strerror (errno));
328 struct sockaddr_un un;
329 memset (&un, 0,
sizeof (un));
330 un.sun_family = AF_UNIX;
331 int status = bind (sock, (
struct sockaddr*)&un,
sizeof (sa_family_t));
332 NS_ABORT_MSG_IF (status == -1,
"TapBridge::CreateTap(): Could not bind(): errno = " << std::strerror (errno));
343 socklen_t len =
sizeof (un);
344 status = getsockname (sock, (
struct sockaddr*)&un, &len);
345 NS_ABORT_MSG_IF (status == -1,
"TapBridge::CreateTap(): Could not getsockname(): errno = " << std::strerror (errno));
351 NS_LOG_INFO (
"Encoded Unix socket as \"" << path <<
"\"");
369 pid_t pid = ::fork ();
408 NS_FATAL_ERROR (
"TapBridge::CreateTap(): Tap device IP configuration requested but neither IP address nor IP netmask is provided");
413 Ipv4Mask ipv4Mask (
"255.255.255.255");
417 uint32_t index = ipv4->GetInterfaceForDevice (nd);
418 if (ipv4->GetNAddresses (index) > 1)
420 NS_LOG_WARN (
"Underlying bridged NetDevice has multiple IP addresses; using first one.");
422 ipv4Address = ipv4->GetAddress (index, 0).GetLocal ();
427 ipv4Mask = ipv4->GetAddress (index, 0).GetMask ();
443 std::ostringstream ossDeviceName;
450 std::ostringstream ossGateway;
458 std::ostringstream ossIp;
461 ossIp <<
"-i" << ipv4Address;
468 std::ostringstream ossMac;
471 ossMac <<
"-m" << mac48Address;
478 std::ostringstream ossNetmask;
481 ossNetmask <<
"-n" << ipv4Mask;
488 std::ostringstream ossMode;
503 std::ostringstream ossPath;
504 ossPath <<
"-p" << path;
508 status = ::execlp (TAP_CREATOR,
510 ossDeviceName.str ().c_str (),
511 ossGateway.str ().c_str (),
512 ossIp.str ().c_str (),
513 ossMac.str ().c_str (),
514 ossNetmask.str ().c_str (),
515 ossMode.str ().c_str (),
516 ossPath.str ().c_str (),
523 NS_FATAL_ERROR (
"TapBridge::CreateTap(): Back from execlp(), errno = " << ::strerror (errno));
533 pid_t waited = waitpid (pid, &st, 0);
534 NS_ABORT_MSG_IF (waited == -1,
"TapBridge::CreateTap(): waitpid() fails, errno = " << std::strerror (errno));
535 NS_ASSERT_MSG (pid == waited,
"TapBridge::CreateTap(): pid mismatch");
544 int exitStatus = WEXITSTATUS (st);
546 "TapBridge::CreateTap(): socket creator exited normally with status " << exitStatus);
550 NS_FATAL_ERROR (
"TapBridge::CreateTap(): socket creator exited abnormally");
568 iov.iov_base = &magic;
569 iov.iov_len =
sizeof(magic);
582 size_t msg_size =
sizeof(int);
583 char control[CMSG_SPACE (msg_size)];
600 msg.msg_control = control;
601 msg.msg_controllen =
sizeof (control);
608 ssize_t bytesRead = recvmsg (sock, &msg, 0);
609 NS_ABORT_MSG_IF (bytesRead !=
sizeof(
int),
"TapBridge::CreateTap(): Wrong byte count from socket creator");
616 struct cmsghdr *cmsg;
617 for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
619 if (cmsg->cmsg_level == SOL_SOCKET &&
620 cmsg->cmsg_type == SCM_RIGHTS)
629 NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
630 int *rawSocket = (
int*)CMSG_DATA (cmsg);
631 NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
637 NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
641 NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
666 NS_LOG_INFO (
"TapBridge::ReadCallback(): Scheduling handler");
702 Ptr<Packet> packet = Create<Packet> (
reinterpret_cast<const uint8_t *
> (buf), len);
720 NS_LOG_LOGIC (
"TapBridge::ForwardToBridgedDevice: Discarding packet as unfit for ns-3 consumption");
733 "TapBridge::ForwardToBridgedDevice: Source addr is broadcast");
741 NS_LOG_LOGIC (
"Learned MacAddr is " << learnedMac <<
": setting ns-3 device to use this address");
750 NS_LOG_LOGIC (
"Forwarding packet to ns-3 device via Send()");
870 NS_ASSERT_MSG (
m_node != 0,
"TapBridge::SetBridgedDevice: Bridge not installed in a node");
871 NS_ASSERT_MSG (bridgedDevice !=
this,
"TapBridge::SetBridgedDevice: Cannot bridge to self");
876 NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support eui 48 addresses: cannot be added to bridge.");
881 NS_FATAL_ERROR (
"TapBridge::SetBridgedDevice: Device does not support SendFrom: cannot be added to bridge.");
902 NS_LOG_LOGIC (
"Discarding packet stolen from bridged device " << device);
915 NS_LOG_FUNCTION (device << packet << protocol << src << dst << packetType);
1109 NS_FATAL_ERROR (
"TapBridge::Send: You may not call Send on a TapBridge directly");
1117 NS_FATAL_ERROR (
"TapBridge::Send: You may not call SendFrom on a TapBridge directly");
uint32_t RemoveHeader(Header &header)
static bool IsMatchingType(const Address &address)
virtual Ptr< Channel > GetChannel(void) const
virtual void DoDispose(void)
static Ipv4Mask GetOnes(void)
keep track of time values and allow control of 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)
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)
void SetBridgedNetDevice(Ptr< NetDevice > bridgedDevice)
Set the ns-3 net device to bridge.
void SetMode(TapBridge::Mode mode)
hold variables of type string
virtual bool SetMtu(const uint16_t mtu)
a class to represent an Ipv4 address mask
uint64_t GetUid(void) const
void StartTapDevice(void)
void Start(Time tStart)
Set a start time for the device.
uint32_t GetSize(void) const
bool IsBroadcast(void) const
virtual void DoDispose(void)
static void Cancel(const EventId &id)
#define NS_LOG_FUNCTION_NOARGS()
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)
static TypeId GetTypeId(void)
#define NS_FATAL_ERROR(msg)
fatal error handling
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. Make the string pret...
virtual void AddLinkChangeCallback(Callback< void > callback)
virtual void SetIfIndex(const uint32_t index)
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.
NS_OBJECT_ENSURE_REGISTERED(AntennaModel)
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)
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)
#define NS_LOG_LOGIC(msg)
Ptr< NetDevice > m_bridgedDevice
virtual void SetAddress(Address address)
static Mac48Address ConvertFrom(const Address &address)
void ReadCallback(uint8_t *buf, ssize_t len)
Access to the Ipv4 forwarding table, interfaces, and configuration.
Ptr< Packet > Copy(void) const
std::string m_tapDeviceName
Ptr< TapBridgeFdReader > m_fdReader
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
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
#define NS_ASSERT_MSG(condition, message)
NS_LOG_COMPONENT_DEFINE("TapBridge")
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)
virtual bool IsMulticast(void) const
uint32_t GetId(void) const
virtual bool IsLinkUp(void) const
Network layer to device interface.
hold objects of type ns3::Mac48Address
bool IsEqual(Ipv4Mask other) const
#define NS_LOG_DEBUG(msg)
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. Both limits are inclusive.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if cond is true.
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)
virtual bool SupportsSendFrom() const