/usr/include/ns3.26/ns3/tap-bridge.h is in libns3-dev 3.26+dfsg-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 University of Washington
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef TAP_BRIDGE_H
#define TAP_BRIDGE_H
#include <cstring>
#include "ns3/address.h"
#include "ns3/net-device.h"
#include "ns3/node.h"
#include "ns3/callback.h"
#include "ns3/packet.h"
#include "ns3/traced-callback.h"
#include "ns3/event-id.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/ptr.h"
#include "ns3/mac48-address.h"
#include "ns3/unix-fd-reader.h"
namespace ns3 {
/**
* \ingroup tap-bridge
* Class to perform the actual reading from a socket
*/
class TapBridgeFdReader : public FdReader
{
private:
FdReader::Data DoRead (void);
};
class Node;
/**
* \ingroup tap-bridge
*
* \brief A bridge to make it appear that a real host process is connected to
* an ns-3 net device.
*
* The Tap Bridge lives in a kind of a gray world somewhere between a
* Linux host and an ns-3 bridge device. From the Linux perspective,
* this code appears as the user mode handler for a Tap net device. That
* is, when the Linux host writes to a /dev/tap device (that is either
* manually or automatically created depending on basic operating mode
* -- more on this later), the write is redirected into the TapBridge that
* lives in the ns-3 world; and from this perspective, becomes a read.
* In other words, a Linux process writes a packet to a tap device and
* this packet is redirected to an ns-3 process where it is received by
* the TapBridge as a result of a read operation there. The TapBridge
* then sends the packet to the ns-3 net device to which it is bridged.
* In the other direction, a packet received by an ns-3 net device is
* bridged to the TapBridge (it appears via a callback from that net
* device. The TapBridge then takes that packet and writes it back to
* the host using the Linux TAP mechanism. This write to the device will
* then appear to the Linux host as if a packet has arrived on its
* device.
*
* The upshot is that the Tap Bridge appears to bridge a tap device on a
* Linux host in the "real world" to an ns-3 net device in the simulation
* and make is appear that a ns-3 net device is actually installed in the
* Linux host. In order to do this on the ns-3 side, we need a "ghost
* node" in the simulation to hold the bridged ns-3 net device and the
* TapBridge. This node should not actually do anything else in the
* simulation since its job is simply to make the net device appear in
* Linux. This is not just arbitrary policy, it is because:
*
* - Bits sent to the Tap Bridge from higher layers in the ghost node (using
* the TapBridge Send() method) are completely ignored. The Tap Bridge is
* not, itself, connected to any network, neither in Linux nor in ns-3;
* - The bridged ns-3 net device is has had its receive callback disconnected
* from the ns-3 node and reconnected to the Tap Bridge. All data received
* by a bridged device will be sent to the Linux host and will not be
* received by the node. From the perspective of the ghost node, you can
* send over this device but you cannot ever receive.
*
* Of course, if you understand all of the issues you can take control of
* your own destiny and do whatever you want -- we do not actively
* prevent you from using the ghost node for anything you decide. You
* will be able to perform typical ns-3 operations on the ghost node if
* you so desire. The internet stack, for example, must be there and
* functional on that node in order to participate in IP address
* assignment and global routing. However, as mentioned above,
* interfaces talking any Tap Bridge or associated bridged net devices
* will not work completely. If you understand exactly what you are
* doing, you can set up other interfaces and devices on the ghost node
* and use them; or take advantage of the operational send side of the
* bridged devices to create traffic generators. We generally recommend
* that you treat this node as a ghost of the Linux host and leave it to
* itself, though.
*/
class TapBridge : public NetDevice
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
/**
* Enumeration of the operating modes supported in the class.
*
*/
enum Mode {
ILLEGAL, /**< mode not set */
CONFIGURE_LOCAL, /**< ns-3 creates and configures tap device */
USE_LOCAL, /**< ns-3 uses a pre-created tap, without configuring it */
USE_BRIDGE, /**< ns-3 uses a pre-created tap, and bridges to a bridging net device */
};
TapBridge ();
virtual ~TapBridge ();
/**
* \brief Get the bridged net device.
*
* The bridged net device is the ns-3 device to which this bridge is connected,
*
* \returns the bridged net device.
*/
Ptr<NetDevice> GetBridgedNetDevice (void);
/**
* \brief Set the ns-3 net device to bridge.
*
* This method tells the bridge which ns-3 net device it should use to connect
* the simulation side of the bridge.
*
* \param bridgedDevice device to set
*
* \attention The ns-3 net device that is being set as the device must have an
* an IP address assigned to it before the simulation is run. This address
* will be used to set the hardware address of the host Linux device.
*/
void SetBridgedNetDevice (Ptr<NetDevice> bridgedDevice);
/**
* \brief Set a start time for the device.
*
* The tap bridge consumes a non-trivial amount of time to start. It starts
* up in the context of a scheduled event to ensure that all configuration
* has been completed before extracting the configuration (IP addresses, etc.)
* In order to allow a more reasonable start-up sequence than a thundering
* herd of devices, the time at which each device starts is also configurable
* bot via the Attribute system and via this call.
*
* \param tStart the start time
*/
void Start (Time tStart);
/**
* Set a stop time for the device.
*
* @param tStop the stop time
*
* \see TapBridge::Start
*/
void Stop (Time tStop);
/**
* Set the operating mode of this device.
*
* \param mode The operating mode of this device.
*/
void SetMode (TapBridge::Mode mode);
/**
* Get the operating mode of this device.
*
* \returns The operating mode of this device.
*/
TapBridge::Mode GetMode (void);
//
// The following methods are inherited from NetDevice base class and are
// documented there.
//
virtual void SetIfIndex (const uint32_t index);
virtual uint32_t GetIfIndex (void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);
virtual uint16_t GetMtu (void) const;
virtual bool IsLinkUp (void) const;
virtual void AddLinkChangeCallback (Callback<void> callback);
virtual bool IsBroadcast (void) const;
virtual Address GetBroadcast (void) const;
virtual bool IsMulticast (void) const;
virtual Address GetMulticast (Ipv4Address multicastGroup) const;
virtual bool IsPointToPoint (void) const;
virtual bool IsBridge (void) const;
virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
virtual Ptr<Node> GetNode (void) const;
virtual void SetNode (Ptr<Node> node);
virtual bool NeedsArp (void) const;
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
virtual bool SupportsSendFrom () const;
virtual Address GetMulticast (Ipv6Address addr) const;
protected:
/**
* Call out to a separate process running as suid root in order to get our
* tap device created. We do this to avoid having the entire simulation
* running as root. If this method returns, we'll have a socket waiting
* for us in m_sock that we can use to talk to the tap device.
*/
virtual void DoDispose (void);
/**
* Receives a packet from a bridged Device
* \param device the originating port
* \param packet the received packet
* \param protocol the packet protocol (e.g., Ethertype)
* \param src the packet source
* \param dst the packet destination
* \param packetType the packet type (e.g., host, broadcast, etc.)
* \returns true on success
*/
bool ReceiveFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
Address const &src, Address const &dst, PacketType packetType);
/**
* Receives a packet from a bridged Device
* \param device the originating port
* \param packet the received packet
* \param protocol the packet protocol (e.g., Ethertype)
* \param src the packet source
* \returns true on success
*/
bool DiscardFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
Address const &src);
private:
/**
* Call out to a separate process running as suid root in order to get our
* tap device created. We do this to avoid having the entire simulation
* running as root. If this method returns, we'll have a socket waiting
* for us in m_sock that we can use to talk to the tap device.
*/
void CreateTap (void);
/**
* Spin up the device
*/
void StartTapDevice (void);
/**
* Tear down the device
*/
void StopTapDevice (void);
/**
* Callback to process packets that are read
*/
void ReadCallback (uint8_t *buf, ssize_t len);
/**
* Forward a packet received from the tap device to the bridged ns-3
* device
*
* \param buf A character buffer containing the actual packet bits that were
* received from the host.
* \param len The length of the buffer.
*/
void ForwardToBridgedDevice (uint8_t *buf, ssize_t len);
/**
* The host we are bridged to is in the evil real world. Do some sanity
* checking on a received packet to make sure it isn't too evil for our
* poor naive virginal simulator to handle.
*
* \param packet The packet we received from the host, and which we need
* to check.
* \param src A pointer to the data structure that will get the source
* MAC address of the packet (extracted from the packet Ethernet
* header).
* \param dst A pointer to the data structure that will get the destination
* MAC address of the packet (extracted from the packet Ethernet
* header).
* \param type A pointer to the variable that will get the packet type from
* either the Ethernet header in the case of type interpretation
* (DIX framing) or from the 802.2 LLC header in the case of
* length interpretation (802.3 framing).
* \returns the packet, or null if the packet has been filtered.
*/
Ptr<Packet> Filter (Ptr<Packet> packet, Address *src, Address *dst, uint16_t *type);
/**
* Notifies that the link is up and ready.
*/
void NotifyLinkUp (void);
/**
* Callback used to hook the standard packet receive callback of the TapBridge
* ns-3 net device. This is never called, and therefore no packets will ever
* be received forwarded up the IP stack on the ghost node through this device.
*/
NetDevice::ReceiveCallback m_rxCallback;
/**
* Callback used to hook the promiscuous packet receive callback of the TapBridge
* ns-3 net device. This is never called, and therefore no packets will ever
* be received forwarded up the IP stack on the ghost node through this device.
*
* Note that we intercept the similar callback in the bridged device in order to
* do the actual bridging between the bridged ns-3 net device and the Tap device
* on the host.
*/
NetDevice::PromiscReceiveCallback m_promiscRxCallback;
/**
* Pointer to the (ghost) Node to which we are connected.
*/
Ptr<Node> m_node;
/**
* The ns-3 interface index of this TapBridge net device.
*/
uint32_t m_ifIndex;
/**
* The common mtu to use for the net devices
*/
uint16_t m_mtu;
/**
* The socket (actually interpreted as fd) to use to talk to the Tap device on
* the real internet host.
*/
int m_sock;
/**
* The ID of the ns-3 event used to schedule the start up of the underlying
* host Tap device and ns-3 read thread.
*/
EventId m_startEvent;
/**
* The ID of the ns-3 event used to schedule the tear down of the underlying
* host Tap device and ns-3 read thread.
*/
EventId m_stopEvent;
/**
* Includes the ns-3 read thread used to do blocking reads on the fd
* corresponding to the host device.
*/
Ptr<TapBridgeFdReader> m_fdReader;
/**
* The operating mode of the bridge. Tells basically who creates and
* configures the underlying network tap.
*/
Mode m_mode;
/**
* The (unused) MAC address of the TapBridge net device. Since the TapBridge
* is implemented as a ns-3 net device, it is required to implement certain
* functionality. In this case, the TapBridge is automatically assigned a
* MAC address, but it is not used.
*/
Mac48Address m_address;
/**
* Time to start spinning up the device
*/
Time m_tStart;
/**
* Time to start tearing down the device
*/
Time m_tStop;
/**
* The name of the device to create on the host. If the device name is the
* empty string, we allow the host kernel to choose a name.
*/
std::string m_tapDeviceName;
/**
* The IP address to use as the device default gateway on the host.
*/
Ipv4Address m_tapGateway;
/**
* The IP address to use as the device IP on the host.
*/
Ipv4Address m_tapIp;
/**
* The MAC address to use as the hardware address on the host; only used
* in UseLocal mode. This value comes from the MAC
* address assigned to the bridged ns-3 net device and matches the MAC
* address of the underlying network TAP which we configured to have the
* same value.
*/
Mac48Address m_tapMac;
/**
* The network mask to assign to the device created on the host.
*/
Ipv4Mask m_tapNetmask;
/**
* The ns-3 net device to which we are bridging.
*/
Ptr<NetDevice> m_bridgedDevice;
/**
* Whether the MAC address of the underlying ns-3 device has already been
* rewritten is stored in this variable (for UseLocal/UseBridge mode only).
*/
bool m_ns3AddressRewritten;
/**
* A 64K buffer to hold packet data while it is being sent.
*/
uint8_t *m_packetBuffer;
/**
* a copy of the node id so the read thread doesn't have to GetNode() in
* in order to find the node ID. Thread unsafe reference counting in
* multithreaded apps is not a good thing.
*/
uint32_t m_nodeId;
/**
* Flag indicating whether or not the link is up. In this case,
* whether or not ns-3 is connected to the underlying TAP device
* with a file descriptor.
*/
bool m_linkUp;
/**
* Callbacks to fire if the link changes state (up or down).
*/
TracedCallback<> m_linkChangeCallbacks;
};
} // namespace ns3
#endif /* TAP_BRIDGE_H */
|