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
84 .AddConstructor<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.",
99 MakeIpv4AddressChecker ())
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.",
105 MakeIpv4AddressChecker ())
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.",
111 MakeMac48AddressChecker ())
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.",
117 MakeIpv4MaskChecker ())
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()");
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)
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)
Packet addressed to someone else.
void SetBridgedNetDevice(Ptr< NetDevice > bridgedDevice)
Set the ns-3 net device to bridge.
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
A packet is allocated a new uid when it is created empty or with zero-filled payload.
void StartTapDevice(void)
void Start(Time tStart)
Set a start time for the device.
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
uint32_t GetSize(void) const
bool IsBroadcast(void) const
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
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)
#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.
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)
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)
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
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)
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)
Get the operating mode of this device.
virtual bool IsMulticast(void) const
void ConnectWithoutContext(const CallbackBase &callback)
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.
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.
#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)
Add header to this packet.
virtual bool SupportsSendFrom() const