1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/devices/emulated/emulated-net-device.cc Mon Oct 27 22:01:24 2008 -0700
1.3 @@ -0,0 +1,642 @@
1.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
1.5 +/*
1.6 + * Copyright (c) 2008 University of Washington
1.7 + *
1.8 + * This program is free software; you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License version 2 as
1.10 + * published by the Free Software Foundation;
1.11 + *
1.12 + * This program is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 + * GNU General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU General Public License
1.18 + * along with this program; if not, write to the Free Software
1.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.20 + */
1.21 +
1.22 +#include "emulated-net-device.h"
1.23 +
1.24 +#include "ns3/log.h"
1.25 +#include "ns3/queue.h"
1.26 +#include "ns3/simulator.h"
1.27 +#include "ns3/realtime-simulator-impl.h"
1.28 +#include "ns3/mac48-address.h"
1.29 +#include "ns3/ethernet-header.h"
1.30 +#include "ns3/ethernet-trailer.h"
1.31 +#include "ns3/llc-snap-header.h"
1.32 +#include "ns3/trace-source-accessor.h"
1.33 +#include "ns3/pointer.h"
1.34 +#include "ns3/channel.h"
1.35 +#include "ns3/system-thread.h"
1.36 +#include "ns3/string.h"
1.37 +#include "ns3/boolean.h"
1.38 +
1.39 +#include <sys/socket.h>
1.40 +#include <sys/ioctl.h>
1.41 +#include <net/ethernet.h>
1.42 +#include <net/if.h>
1.43 +#include <netinet/in.h>
1.44 +#include <netpacket/packet.h>
1.45 +#include <arpa/inet.h>
1.46 +
1.47 +NS_LOG_COMPONENT_DEFINE ("EmulatedNetDevice");
1.48 +
1.49 +namespace ns3 {
1.50 +
1.51 +NS_OBJECT_ENSURE_REGISTERED (EmulatedNetDevice);
1.52 +
1.53 +TypeId
1.54 +EmulatedNetDevice::GetTypeId (void)
1.55 +{
1.56 + static TypeId tid = TypeId ("ns3::EmulatedNetDevice")
1.57 + .SetParent<NetDevice> ()
1.58 + .AddConstructor<EmulatedNetDevice> ()
1.59 + .AddAttribute ("Address",
1.60 + "The ns-3 MAC address of this (virtual) device.",
1.61 + Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
1.62 + MakeMac48AddressAccessor (&EmulatedNetDevice::m_address),
1.63 + MakeMac48AddressChecker ())
1.64 + .AddAttribute ("DeviceName",
1.65 + "The name of the underlying real device (e.g. eth1).",
1.66 + StringValue ("eth1"),
1.67 + MakeStringAccessor (&EmulatedNetDevice::m_deviceName),
1.68 + MakeStringChecker ())
1.69 + .AddAttribute ("Start",
1.70 + "The simulation time at which to spin up the device thread.",
1.71 + TimeValue (Seconds (0.)),
1.72 + MakeTimeAccessor (&EmulatedNetDevice::m_tStart),
1.73 + MakeTimeChecker ())
1.74 + .AddAttribute ("Stop",
1.75 + "The simulation time at which to tear down the device thread.",
1.76 + TimeValue (Seconds (0.)),
1.77 + MakeTimeAccessor (&EmulatedNetDevice::m_tStop),
1.78 + MakeTimeChecker ())
1.79 + .AddAttribute ("TxQueue",
1.80 + "A queue to use as the transmit queue in the device.",
1.81 + PointerValue (),
1.82 + MakePointerAccessor (&EmulatedNetDevice::m_queue),
1.83 + MakePointerChecker<Queue> ())
1.84 + .AddTraceSource ("Rx",
1.85 + "Trace source to fire on reception of a MAC packet.",
1.86 + MakeTraceSourceAccessor (&EmulatedNetDevice::m_rxTrace))
1.87 + .AddTraceSource ("Drop",
1.88 + "Trace source to fire on when a MAC packet is dropped.",
1.89 + MakeTraceSourceAccessor (&EmulatedNetDevice::m_dropTrace))
1.90 + ;
1.91 + return tid;
1.92 +}
1.93 +
1.94 +
1.95 +EmulatedNetDevice::EmulatedNetDevice ()
1.96 +:
1.97 + m_startEvent (),
1.98 + m_stopEvent (),
1.99 + m_sock (-1),
1.100 + m_readThread (0),
1.101 + m_ifIndex (-1),
1.102 + m_sll_ifindex (-1),
1.103 + m_name ("Emulated NetDevice")
1.104 +{
1.105 + NS_LOG_FUNCTION (this);
1.106 + Start (m_tStart);
1.107 +}
1.108 +
1.109 +EmulatedNetDevice::~EmulatedNetDevice ()
1.110 +{
1.111 +}
1.112 +
1.113 +void
1.114 +EmulatedNetDevice::DoDispose()
1.115 +{
1.116 + NS_LOG_FUNCTION_NOARGS ();
1.117 + m_node = 0;
1.118 + NetDevice::DoDispose ();
1.119 +}
1.120 +
1.121 +void
1.122 +EmulatedNetDevice::Start (Time tStart)
1.123 +{
1.124 + NS_LOG_FUNCTION (tStart);
1.125 +
1.126 + //
1.127 + // Cancel any pending start event and schedule a new one at some relative time in the future.
1.128 + //
1.129 + Simulator::Cancel (m_startEvent);
1.130 + m_startEvent = Simulator::Schedule (tStart, &EmulatedNetDevice::StartDevice, this);
1.131 +}
1.132 +
1.133 + void
1.134 +EmulatedNetDevice::Stop (Time tStop)
1.135 +{
1.136 + NS_LOG_FUNCTION (tStop);
1.137 + //
1.138 + // Cancel any pending stop event and schedule a new one at some relative time in the future.
1.139 + //
1.140 + Simulator::Cancel (m_stopEvent);
1.141 + m_startEvent = Simulator::Schedule (tStop, &EmulatedNetDevice::StopDevice, this);
1.142 +}
1.143 +
1.144 + void
1.145 +EmulatedNetDevice::StartDevice (void)
1.146 +{
1.147 + NS_LOG_FUNCTION_NOARGS ();
1.148 +
1.149 + //
1.150 + // Spin up the emulated net device and start receiving packets.
1.151 + //
1.152 + NS_ASSERT_MSG (m_sock == -1, "EmulatedNetDevice::StartDevice(): Device is already started");
1.153 +
1.154 + NS_LOG_LOGIC ("Creating socket");
1.155 +
1.156 + m_sock = socket (PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1.157 + // m_sock = socket (AF_INET, SOCK_PACKET, htons(ETH_P_ALL));
1.158 + NS_ASSERT_MSG (m_sock != -1, "EmulatedNetDevice::StartDevice(): Unable to open socket");
1.159 +
1.160 + //
1.161 + // Figure out which interface index corresponds to the device name in the corresponding attribute.
1.162 + //
1.163 + struct ifreq ifr;
1.164 + bzero (&ifr, sizeof(ifr));
1.165 + strncpy ((char *)ifr.ifr_name, m_deviceName.c_str (), IFNAMSIZ);
1.166 +
1.167 + NS_LOG_LOGIC ("Getting interface index");
1.168 + int32_t rc = ioctl (m_sock, SIOCGIFINDEX, &ifr);
1.169 + NS_ASSERT_MSG (rc != -1, "EmulatedNetDevice::StartDevice(): Can't get interface index");
1.170 +
1.171 + //
1.172 + // Save the real interface index for later calls to sendto
1.173 + //
1.174 + m_sll_ifindex = ifr.ifr_ifindex;
1.175 +
1.176 + //
1.177 + // Bind the socket to the interface we just found.
1.178 + //
1.179 + struct sockaddr_ll ll;
1.180 + bzero (&ll, sizeof(ll));
1.181 +
1.182 + ll.sll_family = AF_PACKET;
1.183 + ll.sll_ifindex = m_sll_ifindex;
1.184 + ll.sll_protocol = htons(ETH_P_ALL);
1.185 +
1.186 + NS_LOG_LOGIC ("Binding socket to interface");
1.187 +
1.188 + rc = bind (m_sock, (struct sockaddr *)&ll, sizeof (ll));
1.189 + NS_ASSERT_MSG (rc != -1, "EmulatedNetDevice::StartDevice(): Can't bind to specified interface");
1.190 +
1.191 + //
1.192 + // Now spin up a read thread to read packets.
1.193 + //
1.194 + NS_ASSERT_MSG (m_readThread == 0, "EmulatedNetDevice::StartDevice(): Receive thread is already running");
1.195 +
1.196 + NS_LOG_LOGIC ("Spinning up read thread");
1.197 +
1.198 + m_readThread = Create<SystemThread> (MakeCallback (&EmulatedNetDevice::ReadThread, this));
1.199 + m_readThread->Start ();
1.200 +
1.201 + NotifyLinkUp ();
1.202 +}
1.203 +
1.204 +void
1.205 +EmulatedNetDevice::StopDevice (void)
1.206 +{
1.207 + NS_LOG_FUNCTION_NOARGS ();
1.208 +
1.209 + close (m_sock);
1.210 + m_sock = -1;
1.211 +
1.212 + NS_ASSERT_MSG (m_readThread != 0, "EmulatedNetDevice::StopDevice(): Receive thread is not running");
1.213 +
1.214 + NS_LOG_LOGIC ("Joining read thread");
1.215 + m_readThread->Join ();
1.216 + m_readThread = 0;
1.217 +}
1.218 +
1.219 +void
1.220 +EmulatedNetDevice::ForwardUp (uint8_t *buf, uint32_t len)
1.221 +{
1.222 + NS_LOG_FUNCTION (buf << len);
1.223 +
1.224 + //
1.225 + // Create a packet out of the buffer we received and free that buffer.
1.226 + //
1.227 + Ptr<Packet> packet = Create<Packet> (reinterpret_cast<const uint8_t *> (buf), len);
1.228 + free (buf);
1.229 + buf = 0;
1.230 +
1.231 + //
1.232 + // Trace sinks will expect complete packets, not packets without some of the
1.233 + // headers.
1.234 + //
1.235 + Ptr<Packet> originalPacket = packet->Copy ();
1.236 +
1.237 + //
1.238 + // Checksum the packet
1.239 + //
1.240 + EthernetTrailer trailer;
1.241 + packet->RemoveTrailer (trailer);
1.242 + trailer.CheckFcs (packet);
1.243 +
1.244 + EthernetHeader header (false);
1.245 + packet->RemoveHeader (header);
1.246 +
1.247 + NS_LOG_LOGIC ("Pkt source is " << header.GetSource ());
1.248 + NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
1.249 +
1.250 + //
1.251 + // An IP host group address is mapped to an Ethernet multicast address
1.252 + // by placing the low-order 23-bits of the IP address into the low-order
1.253 + // 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex).
1.254 + //
1.255 + // We are going to receive all packets destined to any multicast address,
1.256 + // which means clearing the low-order 23 bits the header destination
1.257 + //
1.258 + Mac48Address mcDest;
1.259 + uint8_t mcBuf[6];
1.260 +
1.261 + header.GetDestination ().CopyTo (mcBuf);
1.262 + mcBuf[3] &= 0x80;
1.263 + mcBuf[4] = 0;
1.264 + mcBuf[5] = 0;
1.265 + mcDest.CopyFrom (mcBuf);
1.266 +
1.267 + Mac48Address multicast = Mac48Address::ConvertFrom (GetMulticast ());
1.268 + Mac48Address broadcast = Mac48Address::ConvertFrom (GetBroadcast ());
1.269 + Mac48Address destination = Mac48Address::ConvertFrom (GetAddress ());
1.270 +
1.271 + LlcSnapHeader llc;
1.272 + packet->RemoveHeader (llc);
1.273 + uint16_t protocol = llc.GetType ();
1.274 +
1.275 + PacketType packetType;
1.276 +
1.277 + if (header.GetDestination () == broadcast)
1.278 + {
1.279 + NS_LOG_LOGIC ("Pkt destination is PACKET_BROADCAST");
1.280 + packetType = NS3_PACKET_BROADCAST;
1.281 + }
1.282 + else if (mcDest == multicast)
1.283 + {
1.284 + NS_LOG_LOGIC ("Pkt destination is PACKET_MULTICAST");
1.285 + packetType = NS3_PACKET_MULTICAST;
1.286 + }
1.287 + else if (header.GetDestination () == destination)
1.288 + {
1.289 + NS_LOG_LOGIC ("Pkt destination is PACKET_HOST");
1.290 + packetType = NS3_PACKET_HOST;
1.291 + }
1.292 + else
1.293 + {
1.294 + NS_LOG_LOGIC ("Pkt destination is PACKET_OTHERHOST");
1.295 + packetType = NS3_PACKET_OTHERHOST;
1.296 + }
1.297 +
1.298 + if (!m_promiscRxCallback.IsNull ())
1.299 + {
1.300 + NS_LOG_LOGIC ("calling m_promiscRxCallback");
1.301 + m_promiscRxCallback (this, packet->Copy (), protocol, header.GetSource (), header.GetDestination (), packetType);
1.302 + }
1.303 +
1.304 + if (packetType != NS3_PACKET_OTHERHOST)
1.305 + {
1.306 + m_rxTrace (originalPacket);
1.307 + NS_LOG_LOGIC ("calling m_rxCallback");
1.308 + m_rxCallback (this, packet, protocol, header.GetSource ());
1.309 + }
1.310 +}
1.311 +
1.312 +void
1.313 +EmulatedNetDevice::ReadThread (void)
1.314 +{
1.315 + NS_LOG_FUNCTION_NOARGS ();
1.316 +
1.317 + //
1.318 + // It's important to remember that we're in a completely different thread than the simulator is running in. We
1.319 + // need to synchronize with that other thread to get the packet up into ns-3. What we will need to do is to schedule
1.320 + // a method to forward up the packet using the multithreaded simulator we are most certainly running. However, I just
1.321 + // said it -- we are talking about two threads here, so it is very, very dangerous to do any kind of reference couning
1.322 + // on a shared object. Just don't do it. So what we're going to do is to allocate a buffer on the heap and pass that
1.323 + // buffer into the ns-3 context thread where it will create the packet.
1.324 + //
1.325 +
1.326 + int32_t len = -1;
1.327 + struct sockaddr_ll addr;
1.328 + socklen_t addrSize = sizeof (addr);
1.329 +
1.330 + for (;;)
1.331 + {
1.332 + uint32_t bufferSize = 65536;
1.333 + uint8_t *buf = (uint8_t *)malloc (bufferSize);
1.334 + NS_ASSERT_MSG (buf, "EmulatedNetDevice::ReadThread(): malloc packet buffer failed");
1.335 + NS_LOG_LOGIC ("Calling recvfrom");
1.336 + len = recvfrom (m_sock, buf, bufferSize, 0, (struct sockaddr *)&addr, &addrSize);
1.337 +
1.338 + if (len == -1)
1.339 + {
1.340 + free (buf);
1.341 + buf = 0;
1.342 + return;
1.343 + }
1.344 +
1.345 + NS_LOG_INFO ("EmulatedNetDevice::ReadThread(): Received packet");
1.346 + NS_LOG_INFO ("EmulatedNetDevice::ReadThread(): Scheduling handler");
1.347 + DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->ScheduleRealtimeNow (
1.348 + MakeEvent (&EmulatedNetDevice::ForwardUp, this, buf, len));
1.349 + buf = 0;
1.350 + }
1.351 +}
1.352 +
1.353 +bool
1.354 +EmulatedNetDevice::Send (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
1.355 +{
1.356 + NS_LOG_FUNCTION (packet << dest << protocolNumber);
1.357 + //
1.358 + // The immediate questions here are how are we going to encapsulate packets and what do we use as the MAC source and
1.359 + // destination (hardware) addresses?
1.360 + //
1.361 + // If we return false from EmulatedNetDevice::NeedsArp, the ArpIpv4Interface will pass the broadcast address as the
1.362 + // hardware (Ethernet) destination by default. If we return true from EmulatedNetDevice::NeedsArp, then the hardware
1.363 + // destination is actually meaningful, but we'll have an ns-3 ARP running on this device. There can also be an ARP
1.364 + // running on the underlying OS so we have to be very careful, both about multiple ARPs and also about TCP, UDP, etc.
1.365 + //
1.366 + // We are operating in promiscuous mode on the receive side (all ns-3 net devices are required to implement the
1.367 + // promiscuous callback in a meaningful way), so we have an option regarding the hardware addresses. We don't actually have
1.368 + // to use the real hardware addresses and IP addresses of the underlying system. We can completely use MAC-spoofing to
1.369 + // fake out the OS by using the ns-3 assigned MAC address (and also the ns-3 assigned IP addresses). Ns-3 starts its
1.370 + // MAC address allocation using the OUI (vendor-code) 00:00:00 which is unassigned to any organization and is a globally
1.371 + // administered address, so there shouldn't be any collisions with real hardware.
1.372 + //
1.373 + // So what we do is we return true from EmulatedNetDevice::NeedsArp which tells ns-3 to use its own ARP. We spoof the
1.374 + // MAC address of the device and use promiscuous mode to receive traffic destined to that address.
1.375 + //
1.376 + return SendFrom (packet, m_address, dest, protocolNumber);
1.377 +}
1.378 +
1.379 +bool
1.380 +EmulatedNetDevice::SendFrom (Ptr<Packet> packet, const Address &src, const Address &dest, uint16_t protocolNumber)
1.381 +{
1.382 + NS_LOG_FUNCTION (packet << src << dest << protocolNumber);
1.383 +
1.384 + if (IsLinkUp () == false)
1.385 + {
1.386 + NS_LOG_LOGIC ("Link is down, returning");
1.387 + return false;
1.388 + }
1.389 +
1.390 + Mac48Address destination = Mac48Address::ConvertFrom (dest);
1.391 + Mac48Address source = Mac48Address::ConvertFrom (src);
1.392 +
1.393 + NS_LOG_LOGIC ("Transmit packet with UID " << packet->GetUid ());
1.394 + NS_LOG_LOGIC ("Transmit packet from " << source);
1.395 + NS_LOG_LOGIC ("Transmit packet to " << destination);
1.396 +
1.397 +#if 0
1.398 + {
1.399 + struct ifreq ifr;
1.400 + bzero (&ifr, sizeof(ifr));
1.401 + strncpy ((char *)ifr.ifr_name, m_deviceName.c_str (), IFNAMSIZ);
1.402 +
1.403 + NS_LOG_LOGIC ("Getting MAC address");
1.404 + int32_t rc = ioctl (m_sock, SIOCGIFHWADDR, &ifr);
1.405 + NS_ASSERT_MSG (rc != -1, "EmulatedNetDevice::SendFrom(): Can't get MAC address");
1.406 +
1.407 + std::ostringstream oss;
1.408 + oss << std::hex <<
1.409 + (ifr.ifr_hwaddr.sa_data[0] & 0xff) << ":" <<
1.410 + (ifr.ifr_hwaddr.sa_data[1] & 0xff) << ":" <<
1.411 + (ifr.ifr_hwaddr.sa_data[2] & 0xff) << ":" <<
1.412 + (ifr.ifr_hwaddr.sa_data[3] & 0xff) << ":" <<
1.413 + (ifr.ifr_hwaddr.sa_data[4] & 0xff) << ":" <<
1.414 + (ifr.ifr_hwaddr.sa_data[5] & 0xff) << std::dec;
1.415 +
1.416 + NS_LOG_LOGIC ("Fixup source to HW MAC " << oss.str ());
1.417 + source = Mac48Address (oss.str ().c_str ());
1.418 + NS_LOG_LOGIC ("source now " << source);
1.419 + }
1.420 +#endif
1.421 +
1.422 + LlcSnapHeader llc;
1.423 + llc.SetType (protocolNumber);
1.424 + packet->AddHeader (llc);
1.425 +
1.426 + EthernetHeader header (false);
1.427 + header.SetSource (source);
1.428 + header.SetDestination (destination);
1.429 + header.SetLengthType (packet->GetSize ());
1.430 + packet->AddHeader (header);
1.431 +
1.432 + EthernetTrailer trailer;
1.433 + trailer.CalcFcs (packet);
1.434 + packet->AddTrailer (trailer);
1.435 +
1.436 + //
1.437 + // Enqueue and dequeue the packet to hit the tracing hooks.
1.438 + //
1.439 + m_queue->Enqueue (packet);
1.440 + packet = m_queue->Dequeue ();
1.441 +
1.442 + struct sockaddr_ll ll;
1.443 + bzero (&ll, sizeof (ll));
1.444 +
1.445 + ll.sll_family = AF_PACKET;
1.446 + ll.sll_ifindex = m_sll_ifindex;
1.447 + ll.sll_protocol = htons(ETH_P_ALL);
1.448 +
1.449 + NS_LOG_LOGIC ("calling sendto");
1.450 +
1.451 + int32_t rc;
1.452 + rc = sendto (m_sock, packet->PeekData (), packet->GetSize (), 0, reinterpret_cast<struct sockaddr *> (&ll), sizeof (ll));
1.453 +
1.454 + NS_LOG_LOGIC ("sendto returns " << rc);
1.455 +
1.456 + return rc == -1 ? false : true;
1.457 +}
1.458 +
1.459 +void
1.460 +EmulatedNetDevice::SetDataRate(DataRate bps)
1.461 +{
1.462 + NS_LOG_FUNCTION (this << bps);
1.463 + NS_ASSERT_MSG (false, "EmulatedNetDevice::SetDataRate(): Unable.");
1.464 +}
1.465 +
1.466 +void
1.467 +EmulatedNetDevice::SetQueue (Ptr<Queue> q)
1.468 +{
1.469 + NS_LOG_FUNCTION (this << q);
1.470 + m_queue = q;
1.471 +}
1.472 +
1.473 +Ptr<Queue>
1.474 +EmulatedNetDevice::GetQueue(void) const
1.475 +{
1.476 + NS_LOG_FUNCTION_NOARGS ();
1.477 + return m_queue;
1.478 +}
1.479 +
1.480 +void
1.481 +EmulatedNetDevice::NotifyLinkUp (void)
1.482 +{
1.483 + m_linkUp = true;
1.484 + if (!m_linkChangeCallback.IsNull ())
1.485 + {
1.486 + m_linkChangeCallback ();
1.487 + }
1.488 +}
1.489 +
1.490 +void
1.491 +EmulatedNetDevice::SetName(const std::string name)
1.492 +{
1.493 + m_name = name;
1.494 +}
1.495 +
1.496 +std::string
1.497 +EmulatedNetDevice::GetName(void) const
1.498 +{
1.499 + return m_name;
1.500 +}
1.501 +
1.502 +void
1.503 +EmulatedNetDevice::SetIfIndex(const uint32_t index)
1.504 +{
1.505 + m_ifIndex = index;
1.506 +}
1.507 +
1.508 +uint32_t
1.509 +EmulatedNetDevice::GetIfIndex(void) const
1.510 +{
1.511 + return m_ifIndex;
1.512 +}
1.513 +
1.514 +Ptr<Channel>
1.515 +EmulatedNetDevice::GetChannel (void) const
1.516 +{
1.517 + NS_ASSERT_MSG (false, "EmulatedNetDevice::GetChannel(): Unable.");
1.518 + return 0;
1.519 +}
1.520 +
1.521 +void
1.522 +EmulatedNetDevice::SetAddress (Mac48Address addr)
1.523 +{
1.524 + NS_LOG_FUNCTION (addr);
1.525 + m_address = addr;
1.526 +}
1.527 +
1.528 +Address
1.529 +EmulatedNetDevice::GetAddress (void) const
1.530 +{
1.531 + NS_LOG_FUNCTION_NOARGS ();
1.532 + return m_address;
1.533 +}
1.534 +
1.535 +bool
1.536 +EmulatedNetDevice::SetMtu (const uint16_t mtu)
1.537 +{
1.538 + NS_ASSERT_MSG (false, "EmulatedNetDevice::SetMtu(): Unable.");
1.539 + return false;
1.540 +}
1.541 +
1.542 +uint16_t
1.543 +EmulatedNetDevice::GetMtu (void) const
1.544 +{
1.545 + struct ifreq ifr;
1.546 + bzero (&ifr, sizeof (ifr));
1.547 + strcpy(ifr.ifr_name, m_deviceName.c_str ());
1.548 +
1.549 + int32_t fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
1.550 +
1.551 + int32_t rc = ioctl(fd, SIOCGIFMTU, &ifr);
1.552 + NS_ASSERT_MSG (rc != -1, "EmulatedNetDevice::GetMtu(): Can't ioctl SIOCGIFMTU");
1.553 +
1.554 + close (fd);
1.555 +
1.556 + return ifr.ifr_mtu;
1.557 +}
1.558 +
1.559 +bool
1.560 +EmulatedNetDevice::IsLinkUp (void) const
1.561 +{
1.562 + return m_linkUp;
1.563 +}
1.564 +
1.565 +void
1.566 +EmulatedNetDevice::SetLinkChangeCallback (Callback<void> callback)
1.567 +{
1.568 + m_linkChangeCallback = callback;
1.569 +}
1.570 +
1.571 +bool
1.572 +EmulatedNetDevice::IsBroadcast (void) const
1.573 +{
1.574 + return true;
1.575 +}
1.576 +
1.577 +Address
1.578 +EmulatedNetDevice::GetBroadcast (void) const
1.579 +{
1.580 + return Mac48Address ("ff:ff:ff:ff:ff:ff");
1.581 +}
1.582 +
1.583 +bool
1.584 +EmulatedNetDevice::IsMulticast (void) const
1.585 +{
1.586 + return false;
1.587 +}
1.588 +
1.589 +Address
1.590 +EmulatedNetDevice::GetMulticast (void) const
1.591 +{
1.592 + return Mac48Address ("01:00:5e:00:00:00");
1.593 +}
1.594 +
1.595 +Address
1.596 +EmulatedNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
1.597 +{
1.598 + return Mac48Address ("01:00:5e:00:00:00");
1.599 +}
1.600 +
1.601 +bool
1.602 +EmulatedNetDevice::IsPointToPoint (void) const
1.603 +{
1.604 + return false;
1.605 +}
1.606 +
1.607 +void
1.608 +EmulatedNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
1.609 +{
1.610 + NS_ASSERT_MSG (false, "EmulatedNetDevice::SetPromiscReceiveCallback(): Not implemented");
1.611 +}
1.612 +
1.613 + bool
1.614 +EmulatedNetDevice::SupportsSendFrom () const
1.615 +{
1.616 + NS_LOG_FUNCTION_NOARGS ();
1.617 + return true;
1.618 +}
1.619 +
1.620 +
1.621 +Ptr<Node>
1.622 +EmulatedNetDevice::GetNode (void) const
1.623 +{
1.624 + return m_node;
1.625 +}
1.626 +
1.627 +void
1.628 +EmulatedNetDevice::SetNode (Ptr<Node> node)
1.629 +{
1.630 + m_node = node;
1.631 +}
1.632 +
1.633 +bool
1.634 +EmulatedNetDevice::NeedsArp (void) const
1.635 +{
1.636 + return true;
1.637 +}
1.638 +
1.639 +void
1.640 +EmulatedNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
1.641 +{
1.642 + m_rxCallback = cb;
1.643 +}
1.644 +
1.645 +} // namespace ns3
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/src/devices/emulated/emulated-net-device.h Mon Oct 27 22:01:24 2008 -0700
2.3 @@ -0,0 +1,321 @@
2.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2.5 +/*
2.6 + * Copyright (c) 2008 University of Washington
2.7 + *
2.8 + * This program is free software; you can redistribute it and/or modify
2.9 + * it under the terms of the GNU General Public License version 2 as
2.10 + * published by the Free Software Foundation;
2.11 + *
2.12 + * This program is distributed in the hope that it will be useful,
2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 + * GNU General Public License for more details.
2.16 + *
2.17 + * You should have received a copy of the GNU General Public License
2.18 + * along with this program; if not, write to the Free Software
2.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2.20 + */
2.21 +
2.22 +#ifndef EMULATED_NET_DEVICE_H
2.23 +#define EMULATED_NET_DEVICE_H
2.24 +
2.25 +#include <string.h>
2.26 +#include "ns3/address.h"
2.27 +#include "ns3/net-device.h"
2.28 +#include "ns3/node.h"
2.29 +#include "ns3/callback.h"
2.30 +#include "ns3/packet.h"
2.31 +#include "ns3/traced-callback.h"
2.32 +#include "ns3/event-id.h"
2.33 +#include "ns3/nstime.h"
2.34 +#include "ns3/data-rate.h"
2.35 +#include "ns3/ptr.h"
2.36 +#include "ns3/mac48-address.h"
2.37 +#include "ns3/system-thread.h"
2.38 +
2.39 +namespace ns3 {
2.40 +
2.41 +class Queue;
2.42 +
2.43 +/**
2.44 + * \class EmulatedNetDevice
2.45 + * \brief A Device for an Emulated Network Link.
2.46 + */
2.47 +class EmulatedNetDevice : public NetDevice
2.48 +{
2.49 +public:
2.50 + static TypeId GetTypeId (void);
2.51 +
2.52 + /**
2.53 + * Construct a EmulatedNetDevice
2.54 + *
2.55 + * This is the constructor for the EmulatedNetDevice. It takes as a
2.56 + */
2.57 + EmulatedNetDevice ();
2.58 +
2.59 + /**
2.60 + * Destroy a EmulatedNetDevice
2.61 + *
2.62 + * This is the destructor for the EmulatedNetDevice.
2.63 + */
2.64 + virtual ~EmulatedNetDevice ();
2.65 +
2.66 + /**
2.67 + * Set the Data Rate used for transmission of packets.
2.68 + *
2.69 + * @see Attach ()
2.70 + * @param bps the data rate at which this object operates
2.71 + */
2.72 + void SetDataRate (DataRate bps);
2.73 +
2.74 + /**
2.75 + * Set the inteframe gap used to separate packets. The interframe gap
2.76 + * defines the minimum space required between packets sent by this device.
2.77 + *
2.78 + * @param t the interframe gap time
2.79 + */
2.80 + void SetInterframeGap (Time t);
2.81 +
2.82 + /**
2.83 + * Set a start time for the device.
2.84 + *
2.85 + * @param tStart the start time
2.86 + */
2.87 + void Start (Time tStart);
2.88 +
2.89 + /**
2.90 + * Set a stop time for the device.
2.91 + *
2.92 + * @param tStop the stop time
2.93 + */
2.94 + void Stop (Time tStop);
2.95 +
2.96 + /**
2.97 + * Attach a queue to the EmulatedNetDevice.
2.98 + *
2.99 + * The EmulatedNetDevice "owns" a queue that implements a queueing
2.100 + * method such as DropTail or RED.
2.101 + *
2.102 + * @see Queue
2.103 + * @see DropTailQueue
2.104 + * @param queue Ptr to the new queue.
2.105 + */
2.106 + void SetQueue (Ptr<Queue> queue);
2.107 +
2.108 + /**
2.109 + * Receive a packet.
2.110 + *
2.111 + * The EmulatedNetDevice receives packets from its socket reader
2.112 + * and forwards them up the protocol stack. This is the public method
2.113 + * used by the reader to indicate that a packet has arrived at the device.
2.114 + *
2.115 + * @param p Ptr to the received packet.
2.116 + */
2.117 + void Receive (Ptr<Packet> p);
2.118 +
2.119 + /**
2.120 + * Assign a MAC address to this device.
2.121 + *
2.122 + * @see Mac48Address
2.123 + * @param addr The new address.
2.124 + */
2.125 + void SetAddress (Mac48Address addr);
2.126 +
2.127 +//
2.128 +// Pure virtual methods inherited from NetDevice we must implement.
2.129 +//
2.130 + virtual void SetName(const std::string name);
2.131 + virtual std::string GetName(void) const;
2.132 +
2.133 + virtual void SetIfIndex(const uint32_t index);
2.134 + virtual uint32_t GetIfIndex(void) const;
2.135 +
2.136 + virtual Ptr<Channel> GetChannel (void) const;
2.137 + virtual Address GetAddress (void) const;
2.138 +
2.139 + virtual bool SetMtu (const uint16_t mtu);
2.140 + virtual uint16_t GetMtu (void) const;
2.141 +
2.142 + virtual bool IsLinkUp (void) const;
2.143 +
2.144 + virtual void SetLinkChangeCallback (Callback<void> callback);
2.145 +
2.146 + virtual bool IsBroadcast (void) const;
2.147 + virtual Address GetBroadcast (void) const;
2.148 +
2.149 + virtual bool IsMulticast (void) const;
2.150 + virtual Address GetMulticast (void) const;
2.151 + virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
2.152 +
2.153 + virtual bool IsPointToPoint (void) const;
2.154 +
2.155 + virtual bool Send(Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber);
2.156 +
2.157 + virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
2.158 +
2.159 + virtual Ptr<Node> GetNode (void) const;
2.160 + virtual void SetNode (Ptr<Node> node);
2.161 +
2.162 + virtual bool NeedsArp (void) const;
2.163 +
2.164 + virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
2.165 + virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
2.166 +
2.167 + virtual bool SupportsSendFrom (void) const;
2.168 +
2.169 +private:
2.170 +
2.171 + virtual void DoDispose (void);
2.172 +
2.173 + /**
2.174 + * Get a copy of the attached Queue.
2.175 + *
2.176 + * This method is provided for any derived class that may need to get
2.177 + * direct access to the underlying queue.
2.178 + *
2.179 + * @returns Ptr to the queue.
2.180 + */
2.181 + Ptr<Queue> GetQueue(void) const;
2.182 +
2.183 + /**
2.184 + * Spin up the device
2.185 + */
2.186 + void StartDevice (void);
2.187 +
2.188 + /**
2.189 + * Tear down the device
2.190 + */
2.191 + void StopDevice (void);
2.192 +
2.193 + /**
2.194 + * Loop to read and process packets
2.195 + */
2.196 + void ReadThread (void);
2.197 +
2.198 + /**
2.199 + * Method to handle received packets. Synchronized with simulator via ScheduleNow from ReadThread.
2.200 + */
2.201 + void ForwardUp (uint8_t *buf, uint32_t len);
2.202 +
2.203 + /**
2.204 + * Adds the necessary headers and trailers to a packet of data in order to
2.205 + * respect the protocol implemented by the agent.
2.206 + */
2.207 + void AddHeader(Ptr<Packet> p, uint16_t protocolNumber);
2.208 +
2.209 + /**
2.210 + * Removes, from a packet of data, all headers and trailers that
2.211 + * relate to the protocol implemented by the agent
2.212 + * \return Returns true if the packet should be forwarded up the
2.213 + * protocol stack.
2.214 + */
2.215 + bool ProcessHeader(Ptr<Packet> p, uint16_t& param);
2.216 +
2.217 + /**
2.218 + * Start Sending a Packet Down the Wire.
2.219 + *
2.220 + * @returns true if success, false on failure
2.221 + */
2.222 + bool TransmitStart (Ptr<Packet> p);
2.223 +
2.224 + void NotifyLinkUp (void);
2.225 +
2.226 + /**
2.227 + * The Queue which this EmulatedNetDevice uses as a packet source.
2.228 + * Management of this Queue has been delegated to the EmulatedNetDevice
2.229 + * and it has the responsibility for deletion.
2.230 + * @see class Queue
2.231 + * @see class DropTailQueue
2.232 + */
2.233 + Ptr<Queue> m_queue;
2.234 +
2.235 + /**
2.236 + * The trace source for the packet reception events that the device can
2.237 + * fire.
2.238 + *
2.239 + * @see class CallBackTraceSource
2.240 + */
2.241 + TracedCallback<Ptr<const Packet> > m_rxTrace;
2.242 +
2.243 + /**
2.244 + * The trace source for the packet drop events that the device can
2.245 + * fire.
2.246 + *
2.247 + * @see class CallBackTraceSource
2.248 + */
2.249 + TracedCallback<Ptr<const Packet> > m_dropTrace;
2.250 +
2.251 + /**
2.252 + * Time to start spinning up the device
2.253 + */
2.254 + Time m_tStart;
2.255 +
2.256 + /**
2.257 + * Time to start tearing down the device
2.258 + */
2.259 + Time m_tStop;
2.260 +
2.261 + EventId m_startEvent;
2.262 + EventId m_stopEvent;
2.263 +
2.264 + int32_t m_sock;
2.265 +
2.266 + Ptr<SystemThread> m_readThread;
2.267 +
2.268 + /**
2.269 + * The Node to which this device is attached.
2.270 + */
2.271 + Ptr<Node> m_node;
2.272 +
2.273 + /**
2.274 + * The MAC address which has been assigned to this device.
2.275 + */
2.276 + Mac48Address m_address;
2.277 +
2.278 + /**
2.279 + * The callback used to notify higher layers that a packet has been received.
2.280 + */
2.281 + NetDevice::ReceiveCallback m_rxCallback;
2.282 +
2.283 + /**
2.284 + * The callback used to notify higher layers that a packet has been received in promiscuous mode.
2.285 + */
2.286 + NetDevice::PromiscReceiveCallback m_promiscRxCallback;
2.287 +
2.288 + /**
2.289 + * The ns-3 interface index (in the sense of net device index) that has been assigned to this network device.
2.290 + */
2.291 + uint32_t m_ifIndex;
2.292 +
2.293 + /**
2.294 + * The Unix interface index that we got from the system and which corresponds to the interface (e.g., "eth1")
2.295 + * we are using to talk to the network. Valid when m_sock is valid.
2.296 + */
2.297 + int32_t m_sll_ifindex;
2.298 +
2.299 + /**
2.300 + * The human readable name of this device.
2.301 + */
2.302 + std::string m_name;
2.303 +
2.304 + /**
2.305 + * Flag indicating whether or not the link is up. In this case,
2.306 + * whether or not the device is connected to a channel.
2.307 + */
2.308 + bool m_linkUp;
2.309 +
2.310 + /**
2.311 + * Callback to fire if the link changes state (up or down).
2.312 + */
2.313 + Callback<void> m_linkChangeCallback;
2.314 +
2.315 + /**
2.316 + * The unix/linux name of the underlying device (e.g., eth0)
2.317 + */
2.318 + std::string m_deviceName;
2.319 +};
2.320 +
2.321 +} // namespace ns3
2.322 +
2.323 +#endif // EMULATED_NET_DEVICE_H
2.324 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/src/devices/emulated/emulated.h Mon Oct 27 22:01:24 2008 -0700
3.3 @@ -0,0 +1,10 @@
3.4 +/**
3.5 + * \ingroup devices
3.6 + * \defgroup Emulated Emulated Net Device Model
3.7 + *
3.8 + * \section Emulated Net Device Model
3.9 + *
3.10 + * This is a description of the emulated network device model.
3.11 + *
3.12 + * It is very detailed and comprehensive and answers all possible questions.
3.13 + */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/src/devices/emulated/waf Mon Oct 27 22:01:24 2008 -0700
4.3 @@ -0,0 +1,1 @@
4.4 +exec "`dirname "$0"`"/../../../waf "$@"
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/src/devices/emulated/wscript Mon Oct 27 22:01:24 2008 -0700
5.3 @@ -0,0 +1,14 @@
5.4 +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
5.5 +
5.6 +
5.7 +def build(bld):
5.8 + module = bld.create_ns3_module('emulated', ['node'])
5.9 + module.source = [
5.10 + 'emulated-net-device.cc',
5.11 + ]
5.12 + headers = bld.create_obj('ns3header')
5.13 + headers.module = 'emulated'
5.14 + headers.source = [
5.15 + 'emulated-net-device.h',
5.16 + ]
5.17 +
6.1 --- a/src/devices/emutap/host-tap-net-device.cc Mon Oct 27 13:01:28 2008 -0700
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,194 +0,0 @@
6.4 -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
6.5 -/*
6.6 - * Copyright (c) 2008 INRIA
6.7 - *
6.8 - * This program is free software; you can redistribute it and/or modify
6.9 - * it under the terms of the GNU General Public License version 2 as
6.10 - * published by the Free Software Foundation;
6.11 - *
6.12 - * This program is distributed in the hope that it will be useful,
6.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.15 - * GNU General Public License for more details.
6.16 - *
6.17 - * You should have received a copy of the GNU General Public License
6.18 - * along with this program; if not, write to the Free Software
6.19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6.20 - *
6.21 - * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
6.22 - */
6.23 -#include "host-tap-net-device.h"
6.24 -#include "ns3/node.h"
6.25 -#include "ns3/tap-channel.h"
6.26 -#include "ns3/log.h"
6.27 -
6.28 -NS_LOG_COMPONENT_DEFINE ("HostTapNetDevice");
6.29 -
6.30 -namespace ns3 {
6.31 -
6.32 -TypeId
6.33 -HostTapNetDevice::GetTypeId (void)
6.34 -{
6.35 - static TypeId tid = TypeId ("ns3::HostTapNetDevice")
6.36 - .SetParent<NetDevice> ()
6.37 - .AddConstructor<HostTapNetDevice> ()
6.38 - ;
6.39 - return tid;
6.40 -}
6.41 -
6.42 -HostTapNetDevice::HostTapNetDevice ()
6.43 - : m_node (0),
6.44 - m_mtu (0xffff),
6.45 - m_name (""),
6.46 - m_ifIndex (0)
6.47 -{
6.48 - NS_LOG_FUNCTION (this);
6.49 -}
6.50 -
6.51 -void
6.52 -HostTapNetDevice::SetChannel (Ptr<TapChannel> channel)
6.53 -{
6.54 - m_channel = channel;
6.55 - m_channel->SetHostDevice (this);
6.56 -}
6.57 -
6.58 -void
6.59 -HostTapNetDevice::SetAddress (Mac48Address address)
6.60 -{
6.61 - m_address = address;
6.62 -}
6.63 -
6.64 -Mac48Address
6.65 -HostTapNetDevice::GetMacAddress (void) const
6.66 -{
6.67 - return m_address;
6.68 -}
6.69 -
6.70 -void
6.71 -HostTapNetDevice::SetName(const std::string name)
6.72 -{
6.73 - m_name = name;
6.74 -}
6.75 -std::string
6.76 -HostTapNetDevice::GetName(void) const
6.77 -{
6.78 - return m_name;
6.79 -}
6.80 -void
6.81 -HostTapNetDevice::SetIfIndex(const uint32_t index)
6.82 -{
6.83 - m_ifIndex = index;
6.84 -}
6.85 -uint32_t
6.86 -HostTapNetDevice::GetIfIndex(void) const
6.87 -{
6.88 - return m_ifIndex;
6.89 -}
6.90 -Ptr<Channel>
6.91 -HostTapNetDevice::GetChannel (void) const
6.92 -{
6.93 - return m_channel;
6.94 -}
6.95 -Address
6.96 -HostTapNetDevice::GetAddress (void) const
6.97 -{
6.98 - return m_address;
6.99 -}
6.100 -bool
6.101 -HostTapNetDevice::SetMtu (const uint16_t mtu)
6.102 -{
6.103 - m_mtu = mtu;
6.104 - return true;
6.105 -}
6.106 -uint16_t
6.107 -HostTapNetDevice::GetMtu (void) const
6.108 -{
6.109 - return m_mtu;
6.110 -}
6.111 -bool
6.112 -HostTapNetDevice::IsLinkUp (void) const
6.113 -{
6.114 - return true;
6.115 -}
6.116 -void
6.117 -HostTapNetDevice::SetLinkChangeCallback (Callback<void> callback)
6.118 -{}
6.119 -bool
6.120 -HostTapNetDevice::IsBroadcast (void) const
6.121 -{
6.122 - return true;
6.123 -}
6.124 -Address
6.125 -HostTapNetDevice::GetBroadcast (void) const
6.126 -{
6.127 - return Mac48Address ("ff:ff:ff:ff:ff:ff");
6.128 -}
6.129 -bool
6.130 -HostTapNetDevice::IsMulticast (void) const
6.131 -{
6.132 - return true;
6.133 -}
6.134 -Address
6.135 -HostTapNetDevice::GetMulticast (void) const
6.136 -{
6.137 - return Mac48Address::GetMulticastPrefix ();
6.138 -}
6.139 -Address
6.140 -HostTapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
6.141 -{
6.142 - return Mac48Address::GetMulticast (multicastGroup);
6.143 -}
6.144 -bool
6.145 -HostTapNetDevice::IsPointToPoint (void) const
6.146 -{
6.147 - return false;
6.148 -}
6.149 -bool
6.150 -HostTapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
6.151 -{
6.152 - return false;
6.153 -}
6.154 -bool
6.155 -HostTapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
6.156 -{
6.157 - return false;
6.158 -}
6.159 -Ptr<Node>
6.160 -HostTapNetDevice::GetNode (void) const
6.161 -{
6.162 - return m_node;
6.163 -}
6.164 -void
6.165 -HostTapNetDevice::SetNode (Ptr<Node> node)
6.166 -{
6.167 - m_node = node;
6.168 -}
6.169 -bool
6.170 -HostTapNetDevice::NeedsArp (void) const
6.171 -{
6.172 - return false;
6.173 -}
6.174 -void
6.175 -HostTapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
6.176 -{}
6.177 -
6.178 -void
6.179 -HostTapNetDevice::DoDispose (void)
6.180 -{
6.181 - NS_LOG_FUNCTION (this);
6.182 - m_node = 0;
6.183 - m_channel = 0;
6.184 - NetDevice::DoDispose ();
6.185 -}
6.186 -
6.187 -void
6.188 -HostTapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
6.189 -{}
6.190 -
6.191 -bool
6.192 -HostTapNetDevice::SupportsSendFrom (void) const
6.193 -{
6.194 - return false;
6.195 -}
6.196 -
6.197 -} // namespace ns3
7.1 --- a/src/devices/emutap/host-tap-net-device.h Mon Oct 27 13:01:28 2008 -0700
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,90 +0,0 @@
7.4 -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
7.5 -/*
7.6 - * Copyright (c) 2008 INRIA
7.7 - *
7.8 - * This program is free software; you can redistribute it and/or modify
7.9 - * it under the terms of the GNU General Public License version 2 as
7.10 - * published by the Free Software Foundation;
7.11 - *
7.12 - * This program is distributed in the hope that it will be useful,
7.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.15 - * GNU General Public License for more details.
7.16 - *
7.17 - * You should have received a copy of the GNU General Public License
7.18 - * along with this program; if not, write to the Free Software
7.19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7.20 - *
7.21 - * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7.22 - */
7.23 -#ifndef HOST_TAP_NET_DEVICE_H
7.24 -#define HOST_TAP_NET_DEVICE_H
7.25 -
7.26 -#include "ns3/net-device.h"
7.27 -#include "ns3/mac48-address.h"
7.28 -#include "ns3/traced-callback.h"
7.29 -#include <stdint.h>
7.30 -#include <string>
7.31 -
7.32 -namespace ns3 {
7.33 -
7.34 -class Node;
7.35 -class TapChannel;
7.36 -
7.37 -
7.38 -/**
7.39 - * \ingroup netdevice
7.40 - *
7.41 - * \brief a NetDevice to get packets to and from a host tap device.
7.42 - */
7.43 -class HostTapNetDevice : public NetDevice
7.44 -{
7.45 -public:
7.46 - static TypeId GetTypeId (void);
7.47 - HostTapNetDevice ();
7.48 -
7.49 - void SetAddress (Mac48Address address);
7.50 - void SetChannel (Ptr<TapChannel> channel);
7.51 -
7.52 - Mac48Address GetMacAddress (void) const;
7.53 -
7.54 - // inherited from NetDevice base class.
7.55 - virtual void SetName(const std::string name);
7.56 - virtual std::string GetName(void) const;
7.57 - virtual void SetIfIndex(const uint32_t index);
7.58 - virtual uint32_t GetIfIndex(void) const;
7.59 - virtual Ptr<Channel> GetChannel (void) const;
7.60 - virtual Address GetAddress (void) const;
7.61 - virtual bool SetMtu (const uint16_t mtu);
7.62 - virtual uint16_t GetMtu (void) const;
7.63 - virtual bool IsLinkUp (void) const;
7.64 - virtual void SetLinkChangeCallback (Callback<void> callback);
7.65 - virtual bool IsBroadcast (void) const;
7.66 - virtual Address GetBroadcast (void) const;
7.67 - virtual bool IsMulticast (void) const;
7.68 - virtual Address GetMulticast (void) const;
7.69 - virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
7.70 - virtual bool IsPointToPoint (void) const;
7.71 - virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
7.72 - virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
7.73 - virtual Ptr<Node> GetNode (void) const;
7.74 - virtual void SetNode (Ptr<Node> node);
7.75 - virtual bool NeedsArp (void) const;
7.76 - virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
7.77 - virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
7.78 - virtual bool SupportsSendFrom (void) const;
7.79 -
7.80 -protected:
7.81 - virtual void DoDispose (void);
7.82 -private:
7.83 - Ptr<Node> m_node;
7.84 - uint16_t m_mtu;
7.85 - std::string m_name;
7.86 - uint32_t m_ifIndex;
7.87 - Mac48Address m_address;
7.88 - Ptr<TapChannel> m_channel;
7.89 -};
7.90 -
7.91 -} // namespace ns3
7.92 -
7.93 -#endif /* HOST_TAP_NET_DEVICE_H */
8.1 --- a/src/devices/emutap/tap-channel.cc Mon Oct 27 13:01:28 2008 -0700
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,61 +0,0 @@
8.4 -#include "tap-channel.h"
8.5 -#include "host-tap-net-device.h"
8.6 -#include "tap-net-device.h"
8.7 -
8.8 -namespace ns3 {
8.9 -
8.10 -
8.11 -TapChannel::TapChannel ()
8.12 - : m_hostDevice (0),
8.13 - m_device (0)
8.14 -{}
8.15 -
8.16 -void
8.17 -TapChannel::DoDispose (void)
8.18 -{
8.19 - m_device = 0;
8.20 - m_hostDevice = 0;
8.21 - Channel::DoDispose ();
8.22 -}
8.23 -
8.24 -void
8.25 -TapChannel::SetDevice (Ptr<TapNetDevice> device)
8.26 -{
8.27 - m_device = device;
8.28 -}
8.29 -
8.30 -void
8.31 -TapChannel::SetHostDevice (Ptr<HostTapNetDevice> device)
8.32 -{
8.33 - m_hostDevice = device;
8.34 -}
8.35 -
8.36 -Ptr<HostTapNetDevice>
8.37 -TapChannel::GetHostDevice (void) const
8.38 -{
8.39 - return m_hostDevice;
8.40 -}
8.41 -
8.42 -uint32_t
8.43 -TapChannel::GetNDevices (void) const
8.44 -{
8.45 - return 2;
8.46 -}
8.47 -Ptr<NetDevice>
8.48 -TapChannel::GetDevice (uint32_t i) const
8.49 -{
8.50 - if (i == 0)
8.51 - {
8.52 - return m_device;
8.53 - }
8.54 - else if (i == 1)
8.55 - {
8.56 - return m_hostDevice;
8.57 - }
8.58 - else
8.59 - {
8.60 - return 0;
8.61 - }
8.62 -}
8.63 -
8.64 -} // namespace ns3
9.1 --- a/src/devices/emutap/tap-channel.h Mon Oct 27 13:01:28 2008 -0700
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,36 +0,0 @@
9.4 -#ifndef TAP_CHANNEL_H
9.5 -#define TAP_CHANNEL_H
9.6 -
9.7 -#include "ns3/channel.h"
9.8 -
9.9 -namespace ns3 {
9.10 -
9.11 -class HostTapNetDevice;
9.12 -class TapNetDevice;
9.13 -class NetDevice;
9.14 -
9.15 -
9.16 -class TapChannel : public Channel
9.17 -{
9.18 -public:
9.19 - TapChannel ();
9.20 -
9.21 - void SetHostDevice (Ptr<HostTapNetDevice> device);
9.22 - void SetDevice (Ptr<TapNetDevice> device);
9.23 -
9.24 - Ptr<HostTapNetDevice> GetHostDevice (void) const;
9.25 -
9.26 - // overriden from Channel base class
9.27 - virtual uint32_t GetNDevices (void) const;
9.28 - virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
9.29 -
9.30 -private:
9.31 - virtual void DoDispose (void);
9.32 -
9.33 - Ptr<HostTapNetDevice> m_hostDevice;
9.34 - Ptr<TapNetDevice> m_device;
9.35 -};
9.36 -
9.37 -} // namespace ns3
9.38 -
9.39 -#endif /* TAP_CHANNEL_H */
10.1 --- a/src/devices/emutap/tap-manager-client.cc Mon Oct 27 13:01:28 2008 -0700
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,180 +0,0 @@
10.4 -#include "tap-manager-client.h"
10.5 -#include "ns3/log.h"
10.6 -#include <sys/socket.h>
10.7 -#include <sys/wait.h>
10.8 -#include <sys/stat.h>
10.9 -#include <linux/un.h>
10.10 -#include <errno.h>
10.11 -#include <string.h>
10.12 -#include <iomanip>
10.13 -#include <iostream>
10.14 -#include <list>
10.15 -
10.16 -
10.17 -NS_LOG_COMPONENT_DEFINE("TapManagerClient");
10.18 -
10.19 -#define TAP_MANAGER "ns3-tap-manager"
10.20 -
10.21 -namespace ns3 {
10.22 -
10.23 -static std::string
10.24 -EncodeAsString (struct sockaddr_un un, int len)
10.25 -{
10.26 - uint8_t *buffer = (uint8_t *)&un;
10.27 - std::ostringstream oss;
10.28 - oss.setf (std::ios::hex, std::ios::basefield);
10.29 - oss.fill('0');
10.30 - for (uint8_t i = 0; i < len; i++)
10.31 - {
10.32 - oss << ":" << std::setw (2) << (uint32_t)buffer[i];
10.33 - }
10.34 - return oss.str ();
10.35 -}
10.36 -
10.37 -bool
10.38 -TapManagerClient::Exists (std::string filename) const
10.39 -{
10.40 - struct stat st;
10.41 - int retval = ::stat (filename.c_str (), &st);
10.42 - return retval == 0;
10.43 -}
10.44 -
10.45 -std::string
10.46 -TapManagerClient::FindManager (void) const
10.47 -{
10.48 - std::list<std::string> locations;
10.49 - locations.push_back ("./src/devices/tap");
10.50 - locations.push_back ("./build/debug/src/devices/tap");
10.51 - locations.push_back ("./build/optimized/src/devices/tap");
10.52 - for (std::list<std::string>::const_iterator i = locations.begin (); i != locations.end (); ++i)
10.53 - {
10.54 - if (Exists (*i + "/" + TAP_MANAGER))
10.55 - {
10.56 - return *i + "/" + TAP_MANAGER;
10.57 - }
10.58 - }
10.59 - NS_FATAL_ERROR ("Could not find manager");
10.60 - return ""; // quiet compiler
10.61 -}
10.62 -
10.63 -int
10.64 -TapManagerClient::AllocateTap (Mac48Address host, Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
10.65 -{
10.66 - NS_LOG_FUNCTION (host << ad << mask << gateway);
10.67 - // create a socket to get information back from the tap manager.
10.68 - int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
10.69 - if (sock == -1)
10.70 - {
10.71 - NS_FATAL_ERROR ("Socket creation, errno=" << strerror (errno));
10.72 - }
10.73 -
10.74 - struct sockaddr_un un;
10.75 - memset (&un, 0, sizeof (un));
10.76 - un.sun_family = AF_UNIX;
10.77 - int status = bind (sock, (struct sockaddr*)&un, sizeof (sa_family_t)); // let the kernel allocate an endpoint for us.
10.78 - if (status == -1)
10.79 - {
10.80 - NS_FATAL_ERROR ("Could not bind: errno=" << strerror (errno));
10.81 - }
10.82 - socklen_t len = sizeof (un);
10.83 - status = getsockname (sock, (struct sockaddr*)&un, &len);
10.84 - if (status == -1)
10.85 - {
10.86 - NS_FATAL_ERROR ("Could not get socket address: errno=" << strerror (errno));
10.87 - }
10.88 - NS_LOG_DEBUG ("Allocated enpoint=" << EncodeAsString (un, len) << ", len=" << len);
10.89 -
10.90 - pid_t pid = ::fork ();
10.91 - if (pid == 0)
10.92 - {
10.93 - // child.
10.94 - NS_LOG_DEBUG ("Child");
10.95 -
10.96 - std::ostringstream oss;
10.97 - oss << "--path=" << EncodeAsString (un, len);
10.98 - std::string pathArg = oss.str ();
10.99 - oss.str ("");
10.100 - oss << "--mac-addr=" << host;
10.101 - std::string hostArg = oss.str ();
10.102 - oss.str ("");
10.103 - oss << "--ip-addr=" << ad;
10.104 - std::string ipArg = oss.str ();
10.105 - oss.str ("");
10.106 - oss << "--ip-gw=" << gateway;
10.107 - std::string ipGw = oss.str ();
10.108 - oss.str ("");
10.109 - oss << "--ip-netmask=" << mask;
10.110 - std::string ipMask = oss.str ();
10.111 - oss.str ("");
10.112 - status = ::execl (FindManager ().c_str (),
10.113 - TAP_MANAGER,
10.114 - pathArg.c_str (),
10.115 - hostArg.c_str (),
10.116 - ipArg.c_str (),
10.117 - ipGw.c_str (),
10.118 - ipMask.c_str (),
10.119 - (char *)NULL);
10.120 - if (status == -1)
10.121 - {
10.122 - NS_LOG_ERROR ("Cannot execl tap-manager, errno=" << ::strerror (errno));
10.123 - }
10.124 - ::_exit (-1);
10.125 - }
10.126 - else
10.127 - {
10.128 - // parent
10.129 - NS_LOG_DEBUG ("Parent");
10.130 - int st;
10.131 - pid_t waited = waitpid (pid, &st, 0);
10.132 - if (waited == -1)
10.133 - {
10.134 - NS_FATAL_ERROR ("Cannot wait for tap-manager, errno=" << strerror (errno));
10.135 - }
10.136 - NS_ASSERT (pid == waited);
10.137 - if (!WIFEXITED (st))
10.138 - {
10.139 - // tap manager did not complete successfully
10.140 - NS_FATAL_ERROR ("tap-manager did not exit correctly");
10.141 - }
10.142 - else if (WEXITSTATUS (st) != 0)
10.143 - {
10.144 - NS_FATAL_ERROR ("tap-manager did not complete successfully, err=" << WEXITSTATUS (st));
10.145 - }
10.146 - // the tap fd should be available on our unix socket now.
10.147 - size_t msg_size = sizeof(int);
10.148 - char control[CMSG_SPACE(msg_size)];
10.149 - struct cmsghdr *cmsg;
10.150 - uint8_t buffer;
10.151 - struct iovec iov;
10.152 - iov.iov_base = &buffer;
10.153 - iov.iov_len = 1;
10.154 - struct msghdr msg;
10.155 - msg.msg_name = 0;
10.156 - msg.msg_namelen = 0;
10.157 - msg.msg_iov = &iov;
10.158 - msg.msg_iovlen = 1;
10.159 - msg.msg_control = control;
10.160 - msg.msg_controllen = sizeof (control);
10.161 - msg.msg_flags = 0;
10.162 - ssize_t bytesRead = recvmsg (sock, &msg, 0);
10.163 - if (bytesRead != 1)
10.164 - {
10.165 - NS_FATAL_ERROR ("Did not get byte from tap-manager");
10.166 - }
10.167 - NS_LOG_ERROR ("read bytes=" << bytesRead);
10.168 - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
10.169 - {
10.170 - if (cmsg->cmsg_level == SOL_SOCKET &&
10.171 - cmsg->cmsg_type == SCM_RIGHTS)
10.172 - {
10.173 - int *fd = (int*)CMSG_DATA (cmsg);
10.174 - NS_LOG_ERROR ("got tap fd=" << *fd);
10.175 - return *fd;
10.176 - }
10.177 - }
10.178 - NS_FATAL_ERROR ("Did not get SCM_RIGHTS from tap-manager");
10.179 - }
10.180 - return -1;
10.181 -}
10.182 -
10.183 -} // namespace ns3
11.1 --- a/src/devices/emutap/tap-manager-client.h Mon Oct 27 13:01:28 2008 -0700
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,21 +0,0 @@
11.4 -#ifndef TAP_MANAGER_CLIENT_H
11.5 -#define TAP_MANAGER_CLIENT_H
11.6 -
11.7 -#include "ns3/mac48-address.h"
11.8 -#include "ns3/ipv4-address.h"
11.9 -#include <string>
11.10 -
11.11 -namespace ns3 {
11.12 -
11.13 -class TapManagerClient
11.14 -{
11.15 -public:
11.16 - int AllocateTap (Mac48Address host, Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway);
11.17 -private:
11.18 - std::string FindManager (void) const;
11.19 - bool Exists (std::string filename) const;
11.20 -};
11.21 -
11.22 -} // namespace ns3
11.23 -
11.24 -#endif /* TAP_MANAGER_CLIENT_H */
12.1 --- a/src/devices/emutap/tap-manager.cc Mon Oct 27 13:01:28 2008 -0700
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,339 +0,0 @@
12.4 -#include <fcntl.h>
12.5 -#include <sys/ioctl.h>
12.6 -#include <sys/types.h>
12.7 -#include <sys/socket.h>
12.8 -#include <linux/un.h>
12.9 -#include <linux/if.h>
12.10 -#include <linux/if_tun.h>
12.11 -#include <linux/route.h>
12.12 -#include <netinet/in.h>
12.13 -#include <stdint.h>
12.14 -#include <iostream>
12.15 -#include <sstream>
12.16 -#include <iomanip>
12.17 -#include <string.h>
12.18 -#include <errno.h>
12.19 -#include <stdlib.h>
12.20 -
12.21 -#define noENABLE_LOG
12.22 -
12.23 -#define EXIT_ERROR(x, err) \
12.24 - std::cout << __FILE__ << ":" << __LINE__ << ": Unrecoverable Error: " << x; \
12.25 - std::cout << " errno=" << strerror (errno) << std::endl; \
12.26 - exit (err)
12.27 -#ifdef ENABLE_LOG
12.28 -#define LOG(x) \
12.29 - std::cout << x << std::endl;
12.30 -#else
12.31 -#define LOG(x)
12.32 -#endif
12.33 -
12.34 -
12.35 -#define CHECK_ARG(el,var) \
12.36 - { \
12.37 - char start[] = "--" el "="; \
12.38 - if (strncmp (*argv, start, strlen (start)) == 0) \
12.39 - { \
12.40 - var = *argv + strlen (start); \
12.41 - LOG ("--" << el << "=" << var); \
12.42 - } \
12.43 - }
12.44 -
12.45 -#define ASCII_DOT (0x2e)
12.46 -#define ASCII_ZERO (0x30)
12.47 -#define ASCII_a (0x41)
12.48 -#define ASCII_z (0x5a)
12.49 -#define ASCII_A (0x61)
12.50 -#define ASCII_Z (0x7a)
12.51 -#define ASCII_COLON (0x3a)
12.52 -#define ASCII_ZERO (0x30)
12.53 -static char
12.54 -AsciiToLowCase (char c)
12.55 -{
12.56 - if (c >= ASCII_a && c <= ASCII_z) {
12.57 - return c;
12.58 - } else if (c >= ASCII_A && c <= ASCII_Z) {
12.59 - return c + (ASCII_a - ASCII_A);
12.60 - } else {
12.61 - return c;
12.62 - }
12.63 -}
12.64 -static uint32_t
12.65 -AsciiToIpv4 (const char *address)
12.66 -{
12.67 - uint32_t host = 0;
12.68 - while (true) {
12.69 - uint8_t byte = 0;
12.70 - while (*address != ASCII_DOT &&
12.71 - *address != 0) {
12.72 - byte *= 10;
12.73 - byte += *address - ASCII_ZERO;
12.74 - address++;
12.75 - }
12.76 - host <<= 8;
12.77 - host |= byte;
12.78 - if (*address == 0) {
12.79 - break;
12.80 - }
12.81 - address++;
12.82 - }
12.83 - return host;
12.84 -}
12.85 -
12.86 -static void
12.87 -AsciiToMac48 (const char *str, uint8_t addr[6])
12.88 -{
12.89 - int i = 0;
12.90 - while (*str != 0 && i < 6)
12.91 - {
12.92 - uint8_t byte = 0;
12.93 - while (*str != ASCII_COLON && *str != 0)
12.94 - {
12.95 - byte <<= 4;
12.96 - char low = AsciiToLowCase (*str);
12.97 - if (low >= ASCII_a)
12.98 - {
12.99 - byte |= low - ASCII_a + 10;
12.100 - }
12.101 - else
12.102 - {
12.103 - byte |= low - ASCII_ZERO;
12.104 - }
12.105 - str++;
12.106 - }
12.107 - addr[i] = byte;
12.108 - i++;
12.109 - if (*str == 0)
12.110 - {
12.111 - break;
12.112 - }
12.113 - str++;
12.114 - }
12.115 -}
12.116 -
12.117 -static void
12.118 -SetInetAddress (sockaddr *ad, uint32_t networkOrder)
12.119 -{
12.120 - struct sockaddr_in *sin = (struct sockaddr_in*)ad;
12.121 - sin->sin_family = AF_INET;
12.122 - sin->sin_port = 0; // unused
12.123 - sin->sin_addr.s_addr = htonl (networkOrder);
12.124 -}
12.125 -
12.126 -
12.127 -static int
12.128 -CreateTap (const char *mac_addr, const char *ip,
12.129 - const char *gw, const char *netmask)
12.130 -{
12.131 - // opening the tun device usually requires root privs
12.132 - int tap = open ("/dev/net/tun", O_RDWR);
12.133 - if (tap == -1)
12.134 - {
12.135 - EXIT_ERROR ("Could not open /dev/net/tun", 1);
12.136 - }
12.137 - // now, crate a tap device.
12.138 - struct ifreq ifr;
12.139 - // make sure that the tap device will not send us the tun_pi header.
12.140 - ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
12.141 - ifr.ifr_name[0] = 0; // allow the kernel to pick a device name.
12.142 - int status = ioctl (tap, TUNSETIFF, (void *) &ifr);
12.143 - if (status == -1)
12.144 - {
12.145 - EXIT_ERROR ("Could not allocate a tap device", 2);
12.146 - }
12.147 - std::string tapDeviceName = (char *)ifr.ifr_name;
12.148 - LOG ("Allocated TAP device=" << tapDeviceName);
12.149 -
12.150 - // set its hardware address to something we know will be unique within the simulation
12.151 - ifr.ifr_hwaddr.sa_family = 1; // this is ARPHRD_ETHER from if_arp.h
12.152 - AsciiToMac48 (mac_addr, (uint8_t*)ifr.ifr_hwaddr.sa_data);
12.153 - status = ioctl (tap, SIOCSIFHWADDR, &ifr);
12.154 - if (status == -1)
12.155 - {
12.156 - EXIT_ERROR ("Could not set hardware address=" << mac_addr << " for=" << (char *)ifr.ifr_name, 3);
12.157 - }
12.158 - LOG ("device=" << (char *)ifr.ifr_name << " addr=" << mac_addr);
12.159 -
12.160 -
12.161 - // The ip address must be set using an AF_INET socket.
12.162 - int fd = socket (AF_INET, SOCK_DGRAM, 0);
12.163 -
12.164 - // set interface up.
12.165 - status = ioctl (fd, SIOCGIFFLAGS, &ifr);
12.166 - if (status == -1)
12.167 - {
12.168 - EXIT_ERROR ("Could not get flags for interface=" << (char *)ifr.ifr_name, 4);
12.169 - }
12.170 - ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
12.171 - status = ioctl (fd, SIOCSIFFLAGS, &ifr);
12.172 - if (status == -1)
12.173 - {
12.174 - EXIT_ERROR ("Could not bring interface " << (char *)ifr.ifr_name << " up", 5);
12.175 - }
12.176 - LOG ("device=" << (char *)ifr.ifr_name << " is up");
12.177 -
12.178 -
12.179 - // set its ip address.
12.180 - SetInetAddress (&ifr.ifr_addr, AsciiToIpv4 (ip));
12.181 - status = ioctl (fd, SIOCSIFADDR, &ifr);
12.182 - if (status == -1)
12.183 - {
12.184 - EXIT_ERROR ("Could not set ip address=" << ip << " for=" << (char *)ifr.ifr_name, 6);
12.185 - }
12.186 - LOG ("device=" << (char *)ifr.ifr_name << " addr=" << ip);
12.187 -
12.188 - // set its ip mask to be /32
12.189 - SetInetAddress (&ifr.ifr_netmask, 0xffffffff);
12.190 - status = ioctl (fd, SIOCSIFNETMASK, &ifr);
12.191 - if (status == -1)
12.192 - {
12.193 - EXIT_ERROR ("Could not set ip mask=" << netmask << " for=" << (char *)ifr.ifr_name, 7);
12.194 - }
12.195 - LOG ("device=" << (char *)ifr.ifr_name << " mask=" << netmask);
12.196 -
12.197 - // add routing entry for gateway.
12.198 - struct rtentry rt;
12.199 - SetInetAddress (&rt.rt_dst, AsciiToIpv4 (gw));
12.200 - SetInetAddress (&rt.rt_genmask, 0xffffffff);
12.201 - rt.rt_flags = RTF_UP;
12.202 - rt.rt_metric = 2;
12.203 - rt.rt_dev = (char*)tapDeviceName.c_str ();
12.204 - status = ioctl (fd, SIOCADDRT, &rt);
12.205 - if (status == -1)
12.206 - {
12.207 - EXIT_ERROR ("Could not add routing table entry", 8);
12.208 - }
12.209 - LOG ("added routing table entry for gw.");
12.210 -
12.211 - // add routing entry for subnet through gateway.
12.212 - uint32_t network = AsciiToIpv4 (ip) & AsciiToIpv4 (netmask);
12.213 - SetInetAddress (&rt.rt_dst, network);
12.214 - SetInetAddress (&rt.rt_gateway, AsciiToIpv4 (gw));
12.215 - SetInetAddress (&rt.rt_genmask, AsciiToIpv4 (netmask));
12.216 - rt.rt_flags = RTF_UP | RTF_GATEWAY;
12.217 - rt.rt_metric = 2;
12.218 - rt.rt_dev = (char*)tapDeviceName.c_str ();
12.219 - status = ioctl (fd, SIOCADDRT, &rt);
12.220 - if (status == -1)
12.221 - {
12.222 - EXIT_ERROR ("Could not add routing table entry", 9);
12.223 - }
12.224 - LOG ("added routing table entry for subnet.");
12.225 -
12.226 - return tap;
12.227 -}
12.228 -
12.229 -static struct sockaddr_un
12.230 -DecodeFromString (const char *path, socklen_t *len)
12.231 -{
12.232 - sockaddr_un un;
12.233 - uint8_t *buffer = (uint8_t *)&un;
12.234 - std::istringstream iss;
12.235 - iss.str (path);
12.236 - uint8_t n = 0;
12.237 - while (!iss.bad () && !iss.eof () && !iss.fail ())
12.238 - {
12.239 - char c;
12.240 - iss.read (&c, 1);
12.241 - uint32_t tmp;
12.242 - iss >> std::hex >> tmp;
12.243 - //LOG (std::hex << tmp);
12.244 - buffer[n] = tmp;
12.245 - n++;
12.246 - }
12.247 - *len = n;
12.248 - return un;
12.249 -}
12.250 -
12.251 -static void
12.252 -SendFd (const char *path, int fd)
12.253 -{
12.254 - // send back configuration to caller.
12.255 - int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
12.256 - if (sock == -1)
12.257 - {
12.258 - EXIT_ERROR ("Socket creation", 10);
12.259 - }
12.260 - LOG ("Socket Created");
12.261 -
12.262 - socklen_t local_len;
12.263 - struct sockaddr_un local = DecodeFromString (path, &local_len);
12.264 - LOG ("len=" << local_len);
12.265 - int status = connect (sock, (struct sockaddr*)&local, local_len);
12.266 - if (status == -1)
12.267 - {
12.268 - EXIT_ERROR ("Could not connect to caller", 11);
12.269 - }
12.270 - LOG ("Socket Connected");
12.271 -
12.272 - // we send a single byte whose content is meaningless.
12.273 - // we also return as ancillary data the tap file descriptor
12.274 - struct cmsghdr *cmsg;
12.275 - size_t msg_size = sizeof(int);
12.276 - char control[CMSG_SPACE(msg_size)];
12.277 - struct iovec iov;
12.278 - struct msghdr msg;
12.279 - char buffer = 0;
12.280 - iov.iov_base = &buffer;
12.281 - iov.iov_len = 1;
12.282 - msg.msg_name = 0;
12.283 - msg.msg_namelen = 0;
12.284 - msg.msg_iov = &iov;
12.285 - msg.msg_iovlen = 1;
12.286 - msg.msg_control = control;
12.287 - msg.msg_controllen = sizeof (control);
12.288 - msg.msg_flags = 0;
12.289 -
12.290 - cmsg = CMSG_FIRSTHDR(&msg);
12.291 - cmsg->cmsg_level = SOL_SOCKET;
12.292 - cmsg->cmsg_type = SCM_RIGHTS;
12.293 - cmsg->cmsg_len = CMSG_LEN(msg_size);
12.294 - msg.msg_controllen = cmsg->cmsg_len;
12.295 -
12.296 - int *fdptr = (int*) (CMSG_DATA(cmsg));
12.297 - *fdptr = fd;
12.298 -
12.299 - ssize_t len = sendmsg(sock, &msg, 0);
12.300 - if (len == -1)
12.301 - {
12.302 - EXIT_ERROR ("Could not send SCM_RIGHTS", 12);
12.303 - }
12.304 - LOG ("Sent SCM_RIGHTS");
12.305 -}
12.306 -
12.307 -
12.308 -
12.309 -
12.310 -int main (int argc, char *argv[])
12.311 -{
12.312 - char *path = 0;
12.313 - char *mac_addr = 0;
12.314 - char *ip_addr = 0;
12.315 - char *ip_gw = 0;
12.316 - char *ip_netmask = 0;
12.317 - char *stop = 0;
12.318 - argv++;
12.319 - argc--;
12.320 - while (argc > 0)
12.321 - {
12.322 - CHECK_ARG("path", path);
12.323 - CHECK_ARG("mac-addr", mac_addr);
12.324 - CHECK_ARG("ip-addr", ip_addr);
12.325 - CHECK_ARG("ip-gw", ip_gw);
12.326 - CHECK_ARG("ip-netmask", ip_netmask);
12.327 - CHECK_ARG("stop", stop);
12.328 - argv++;
12.329 - argc--;
12.330 - }
12.331 -
12.332 - int tap = CreateTap (mac_addr, ip_addr, ip_gw, ip_netmask);
12.333 -
12.334 - if (stop)
12.335 - {
12.336 - while (1) {}
12.337 - }
12.338 -
12.339 - SendFd (path, tap);
12.340 -
12.341 - return 0;
12.342 -}
13.1 --- a/src/devices/emutap/tap-net-device.cc Mon Oct 27 13:01:28 2008 -0700
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,323 +0,0 @@
13.4 -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
13.5 -/*
13.6 - * Copyright (c) 2008 INRIA
13.7 - *
13.8 - * This program is free software; you can redistribute it and/or modify
13.9 - * it under the terms of the GNU General Public License version 2 as
13.10 - * published by the Free Software Foundation;
13.11 - *
13.12 - * This program is distributed in the hope that it will be useful,
13.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
13.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13.15 - * GNU General Public License for more details.
13.16 - *
13.17 - * You should have received a copy of the GNU General Public License
13.18 - * along with this program; if not, write to the Free Software
13.19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13.20 - *
13.21 - * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
13.22 - */
13.23 -#include "tap-net-device.h"
13.24 -#include "tap-manager-client.h"
13.25 -#include "ns3/node.h"
13.26 -#include "ns3/channel.h"
13.27 -#include "ns3/packet.h"
13.28 -#include "ns3/log.h"
13.29 -#include "ns3/system-thread.h"
13.30 -#include "ns3/realtime-simulator-impl.h"
13.31 -#include "ns3/make-event.h"
13.32 -#include "ns3/simulator.h"
13.33 -#include "ns3/ethernet-header.h"
13.34 -#include "ns3/trace-source-accessor.h"
13.35 -#include "host-tap-net-device.h"
13.36 -#include "tap-channel.h"
13.37 -#include <errno.h>
13.38 -#include <stdlib.h>
13.39 -
13.40 -NS_LOG_COMPONENT_DEFINE ("TapNetDevice");
13.41 -
13.42 -namespace ns3 {
13.43 -
13.44 -TypeId
13.45 -TapNetDevice::GetTypeId (void)
13.46 -{
13.47 - static TypeId tid = TypeId ("ns3::TapNetDevice")
13.48 - .SetParent<NetDevice> ()
13.49 - .AddConstructor<TapNetDevice> ()
13.50 - .AddTraceSource ("Rx", "A packet has been received",
13.51 - MakeTraceSourceAccessor (&TapNetDevice::m_rxTrace))
13.52 - .AddTraceSource ("Tx", "A packet has been sent",
13.53 - MakeTraceSourceAccessor (&TapNetDevice::m_txTrace))
13.54 - .AddTraceSource ("Drop", "A packet has been dropped",
13.55 - MakeTraceSourceAccessor (&TapNetDevice::m_dropTrace))
13.56 - ;
13.57 - return tid;
13.58 -}
13.59 -
13.60 -TapNetDevice::TapNetDevice ()
13.61 - : m_node (0),
13.62 - m_mtu (0xffff),
13.63 - m_name (""),
13.64 - m_ifIndex (0),
13.65 - m_tap (-1)
13.66 -{
13.67 - NS_LOG_FUNCTION (this);
13.68 -}
13.69 -
13.70 -void
13.71 -TapNetDevice::SetChannel (Ptr<TapChannel> channel)
13.72 -{
13.73 - m_channel = channel;
13.74 - m_channel->SetDevice (this);
13.75 -}
13.76 -
13.77 -void
13.78 -TapNetDevice::SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
13.79 -{
13.80 - NS_LOG_FUNCTION (this << ad << mask << gateway);
13.81 - NS_ASSERT (m_tap == -1);
13.82 -
13.83 - Mac48Address hostMacAddress = m_channel->GetHostDevice ()->GetMacAddress ();
13.84 -
13.85 - TapManagerClient manager;
13.86 - m_tap = manager.AllocateTap (hostMacAddress, ad, mask, gateway);
13.87 -
13.88 - m_thread = Create<SystemThread> (MakeCallback (&TapNetDevice::ReadThread, this));
13.89 - m_thread->Start ();
13.90 -}
13.91 -
13.92 -
13.93 -void
13.94 -TapNetDevice::ReadThread (void)
13.95 -{
13.96 - NS_LOG_FUNCTION (this);
13.97 -
13.98 - while (1)
13.99 - {
13.100 - uint8_t *buffer = (uint8_t *)malloc (0xffff);
13.101 - ssize_t bytesRead = read (m_tap, buffer, 0xffff);
13.102 - if (bytesRead == -1)
13.103 - {
13.104 - if (errno == EBADF || errno == EINTR)
13.105 - {
13.106 - // the device was closed from under us by ::DoDispose
13.107 - return;
13.108 - }
13.109 - NS_FATAL_ERROR ("Error reading from tap device: errno=" << strerror (errno));
13.110 - }
13.111 - // Note: we purposedly don't use a smart pointer to manage this packet
13.112 - // because the want to hand over ownership of this packet to the ForwardUp
13.113 - // method.
13.114 - DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->
13.115 - ScheduleRealtimeNow (MakeEvent (&TapNetDevice::ForwardUp, this, buffer, (uint32_t)bytesRead));
13.116 - }
13.117 -}
13.118 -
13.119 -void
13.120 -TapNetDevice::ForwardUp (uint8_t *buffer, uint32_t size)
13.121 -{
13.122 - NS_LOG_FUNCTION (this << buffer << size);
13.123 -
13.124 - // swallow packet reference in smart pointer.
13.125 - Ptr<Packet> packet = Create<Packet> (buffer, size);
13.126 - free (buffer);
13.127 - Ptr<Packet> copy = packet->Copy ();
13.128 -
13.129 - EthernetHeader header = EthernetHeader (false);
13.130 - packet->RemoveHeader (header);
13.131 -
13.132 - uint16_t protocol = header.GetLengthType ();
13.133 - Mac48Address to = header.GetDestination ();
13.134 - Mac48Address from = header.GetSource ();
13.135 -
13.136 - NetDevice::PacketType packetType;
13.137 - if (to == m_address)
13.138 - {
13.139 - packetType = NetDevice::PACKET_HOST;
13.140 - }
13.141 - else if (to.IsBroadcast ())
13.142 - {
13.143 - packetType = NetDevice::PACKET_HOST;
13.144 - }
13.145 - else if (to.IsMulticast ())
13.146 - {
13.147 - packetType = NetDevice::PACKET_MULTICAST;
13.148 - }
13.149 - else
13.150 - {
13.151 - packetType = NetDevice::PACKET_OTHERHOST;
13.152 - }
13.153 - m_rxTrace (copy, from, to);
13.154 - if (packetType != NetDevice::PACKET_OTHERHOST)
13.155 - {
13.156 - m_rxCallback (this, packet, protocol, from);
13.157 - }
13.158 - if (!m_promiscCallback.IsNull ())
13.159 - {
13.160 - m_promiscCallback (this, packet, protocol, from, to, packetType);
13.161 - }
13.162 -}
13.163 -
13.164 -void
13.165 -TapNetDevice::SetAddress (Mac48Address address)
13.166 -{
13.167 - m_address = address;
13.168 -}
13.169 -
13.170 -void
13.171 -TapNetDevice::SetName(const std::string name)
13.172 -{
13.173 - m_name = name;
13.174 -}
13.175 -std::string
13.176 -TapNetDevice::GetName(void) const
13.177 -{
13.178 - return m_name;
13.179 -}
13.180 -void
13.181 -TapNetDevice::SetIfIndex(const uint32_t index)
13.182 -{
13.183 - m_ifIndex = index;
13.184 -}
13.185 -uint32_t
13.186 -TapNetDevice::GetIfIndex(void) const
13.187 -{
13.188 - return m_ifIndex;
13.189 -}
13.190 -Ptr<Channel>
13.191 -TapNetDevice::GetChannel (void) const
13.192 -{
13.193 - return m_channel;
13.194 -}
13.195 -Address
13.196 -TapNetDevice::GetAddress (void) const
13.197 -{
13.198 - return m_address;
13.199 -}
13.200 -bool
13.201 -TapNetDevice::SetMtu (const uint16_t mtu)
13.202 -{
13.203 - m_mtu = mtu;
13.204 - return true;
13.205 -}
13.206 -uint16_t
13.207 -TapNetDevice::GetMtu (void) const
13.208 -{
13.209 - return m_mtu;
13.210 -}
13.211 -bool
13.212 -TapNetDevice::IsLinkUp (void) const
13.213 -{
13.214 - return true;
13.215 -}
13.216 -void
13.217 -TapNetDevice::SetLinkChangeCallback (Callback<void> callback)
13.218 -{}
13.219 -bool
13.220 -TapNetDevice::IsBroadcast (void) const
13.221 -{
13.222 - return true;
13.223 -}
13.224 -Address
13.225 -TapNetDevice::GetBroadcast (void) const
13.226 -{
13.227 - return Mac48Address ("ff:ff:ff:ff:ff:ff");
13.228 -}
13.229 -bool
13.230 -TapNetDevice::IsMulticast (void) const
13.231 -{
13.232 - return true;
13.233 -}
13.234 -Address
13.235 -TapNetDevice::GetMulticast (void) const
13.236 -{
13.237 - return Mac48Address::GetMulticastPrefix ();
13.238 -}
13.239 -Address
13.240 -TapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
13.241 -{
13.242 - return Mac48Address::GetMulticast (multicastGroup);
13.243 -}
13.244 -bool
13.245 -TapNetDevice::IsPointToPoint (void) const
13.246 -{
13.247 - return false;
13.248 -}
13.249 -bool
13.250 -TapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
13.251 -{
13.252 - NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
13.253 - return SendFrom (packet, m_address, dest, protocolNumber);
13.254 -}
13.255 -bool
13.256 -TapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
13.257 -{
13.258 - NS_LOG_FUNCTION (this << packet << source << dest << protocolNumber);
13.259 - Mac48Address to = Mac48Address::ConvertFrom (dest);
13.260 - Mac48Address from = Mac48Address::ConvertFrom (source);
13.261 -
13.262 - EthernetHeader header = EthernetHeader (false);
13.263 - header.SetSource (from);
13.264 - header.SetDestination (to);
13.265 - header.SetLengthType (protocolNumber);
13.266 - packet->AddHeader (header);
13.267 -
13.268 - ssize_t written = write (m_tap, packet->PeekData (), packet->GetSize ());
13.269 - if (written == -1 || written != (ssize_t)packet->GetSize ())
13.270 - {
13.271 - m_dropTrace (packet, from, to);
13.272 - return false;
13.273 - }
13.274 -
13.275 - m_txTrace (packet, from, to);
13.276 -
13.277 - return true;
13.278 -}
13.279 -
13.280 -Ptr<Node>
13.281 -TapNetDevice::GetNode (void) const
13.282 -{
13.283 - return m_node;
13.284 -}
13.285 -void
13.286 -TapNetDevice::SetNode (Ptr<Node> node)
13.287 -{
13.288 - m_node = node;
13.289 -}
13.290 -bool
13.291 -TapNetDevice::NeedsArp (void) const
13.292 -{
13.293 - return true;
13.294 -}
13.295 -void
13.296 -TapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
13.297 -{
13.298 - m_rxCallback = cb;
13.299 -}
13.300 -
13.301 -void
13.302 -TapNetDevice::DoDispose (void)
13.303 -{
13.304 - NS_LOG_FUNCTION (this);
13.305 - close (m_tap);
13.306 - m_thread->Join ();
13.307 - m_thread = 0;
13.308 - m_node = 0;
13.309 - m_channel = 0;
13.310 - NetDevice::DoDispose ();
13.311 -}
13.312 -
13.313 -
13.314 -void
13.315 -TapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
13.316 -{
13.317 - m_promiscCallback = cb;
13.318 -}
13.319 -
13.320 -bool
13.321 -TapNetDevice::SupportsSendFrom (void) const
13.322 -{
13.323 - return true;
13.324 -}
13.325 -
13.326 -} // namespace ns3
14.1 --- a/src/devices/emutap/tap-net-device.h Mon Oct 27 13:01:28 2008 -0700
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,103 +0,0 @@
14.4 -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
14.5 -/*
14.6 - * Copyright (c) 2008 INRIA
14.7 - *
14.8 - * This program is free software; you can redistribute it and/or modify
14.9 - * it under the terms of the GNU General Public License version 2 as
14.10 - * published by the Free Software Foundation;
14.11 - *
14.12 - * This program is distributed in the hope that it will be useful,
14.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.15 - * GNU General Public License for more details.
14.16 - *
14.17 - * You should have received a copy of the GNU General Public License
14.18 - * along with this program; if not, write to the Free Software
14.19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14.20 - *
14.21 - * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
14.22 - */
14.23 -#ifndef TAP_NET_DEVICE_H
14.24 -#define TAP_NET_DEVICE_H
14.25 -
14.26 -#include "ns3/net-device.h"
14.27 -#include "ns3/mac48-address.h"
14.28 -#include "ns3/traced-callback.h"
14.29 -#include <stdint.h>
14.30 -#include <string>
14.31 -
14.32 -namespace ns3 {
14.33 -
14.34 -class Node;
14.35 -class SystemThread;
14.36 -class TapChannel;
14.37 -
14.38 -/**
14.39 - * \ingroup netdevice
14.40 - *
14.41 - * \brief a NetDevice to get packets to and from a host tap device.
14.42 - */
14.43 -class TapNetDevice : public NetDevice
14.44 -{
14.45 -public:
14.46 - static TypeId GetTypeId (void);
14.47 - TapNetDevice ();
14.48 -
14.49 - void SetAddress (Mac48Address address);
14.50 -
14.51 - void SetChannel (Ptr<TapChannel> channel);
14.52 -
14.53 - void SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway);
14.54 -
14.55 - // inherited from NetDevice base class.
14.56 - virtual void SetName(const std::string name);
14.57 - virtual std::string GetName(void) const;
14.58 - virtual void SetIfIndex(const uint32_t index);
14.59 - virtual uint32_t GetIfIndex(void) const;
14.60 - virtual Ptr<Channel> GetChannel (void) const;
14.61 - virtual Address GetAddress (void) const;
14.62 - virtual bool SetMtu (const uint16_t mtu);
14.63 - virtual uint16_t GetMtu (void) const;
14.64 - virtual bool IsLinkUp (void) const;
14.65 - virtual void SetLinkChangeCallback (Callback<void> callback);
14.66 - virtual bool IsBroadcast (void) const;
14.67 - virtual Address GetBroadcast (void) const;
14.68 - virtual bool IsMulticast (void) const;
14.69 - virtual Address GetMulticast (void) const;
14.70 - virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
14.71 - virtual bool IsPointToPoint (void) const;
14.72 - virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
14.73 - virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
14.74 - virtual Ptr<Node> GetNode (void) const;
14.75 - virtual void SetNode (Ptr<Node> node);
14.76 - virtual bool NeedsArp (void) const;
14.77 - virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
14.78 - virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
14.79 - virtual bool SupportsSendFrom (void) const;
14.80 -
14.81 -protected:
14.82 - virtual void DoDispose (void);
14.83 -private:
14.84 - void Receive (Ptr<Packet> packet, uint16_t protocol,
14.85 - Mac48Address to, Mac48Address from);
14.86 - void ForwardUp (uint8_t *buffer, uint32_t size);
14.87 - void ReadThread (void);
14.88 -
14.89 - NetDevice::ReceiveCallback m_rxCallback;
14.90 - NetDevice::PromiscReceiveCallback m_promiscCallback;
14.91 - Ptr<Node> m_node;
14.92 - uint16_t m_mtu;
14.93 - std::string m_name;
14.94 - uint32_t m_ifIndex;
14.95 - Mac48Address m_address;
14.96 - int m_tap;
14.97 - Ptr<SystemThread> m_thread;
14.98 - TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_rxTrace;
14.99 - TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_txTrace;
14.100 - TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_dropTrace;
14.101 - Ptr<TapChannel> m_channel;
14.102 -};
14.103 -
14.104 -} // namespace ns3
14.105 -
14.106 -#endif /* TAP_NET_DEVICE_H */
15.1 --- a/src/devices/emutap/wscript Mon Oct 27 13:01:28 2008 -0700
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,26 +0,0 @@
15.4 -## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
15.5 -
15.6 -
15.7 -def build(bld):
15.8 - obj = bld.create_suid_program('ns3-tap-manager')
15.9 - obj.source = [
15.10 - 'tap-manager.cc',
15.11 - ]
15.12 -
15.13 - module = bld.create_ns3_module('emutap', ['node'])
15.14 - module.uselib = 'CAP'
15.15 - module.source = [
15.16 - 'tap-net-device.cc',
15.17 - 'tap-manager-client.cc',
15.18 - 'tap-channel.cc',
15.19 - 'host-tap-net-device.cc',
15.20 - ]
15.21 - headers = bld.create_obj('ns3header')
15.22 - headers.module = 'emutap'
15.23 - headers.source = [
15.24 - 'tap-net-device.h',
15.25 - 'host-tap-net-device.h',
15.26 - 'tap-channel.h',
15.27 - ]
15.28 -
15.29 -
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/src/devices/tap/host-tap-net-device.cc Mon Oct 27 22:01:24 2008 -0700
16.3 @@ -0,0 +1,194 @@
16.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
16.5 +/*
16.6 + * Copyright (c) 2008 INRIA
16.7 + *
16.8 + * This program is free software; you can redistribute it and/or modify
16.9 + * it under the terms of the GNU General Public License version 2 as
16.10 + * published by the Free Software Foundation;
16.11 + *
16.12 + * This program is distributed in the hope that it will be useful,
16.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16.15 + * GNU General Public License for more details.
16.16 + *
16.17 + * You should have received a copy of the GNU General Public License
16.18 + * along with this program; if not, write to the Free Software
16.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16.20 + *
16.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
16.22 + */
16.23 +#include "host-tap-net-device.h"
16.24 +#include "ns3/node.h"
16.25 +#include "ns3/tap-channel.h"
16.26 +#include "ns3/log.h"
16.27 +
16.28 +NS_LOG_COMPONENT_DEFINE ("HostTapNetDevice");
16.29 +
16.30 +namespace ns3 {
16.31 +
16.32 +TypeId
16.33 +HostTapNetDevice::GetTypeId (void)
16.34 +{
16.35 + static TypeId tid = TypeId ("ns3::HostTapNetDevice")
16.36 + .SetParent<NetDevice> ()
16.37 + .AddConstructor<HostTapNetDevice> ()
16.38 + ;
16.39 + return tid;
16.40 +}
16.41 +
16.42 +HostTapNetDevice::HostTapNetDevice ()
16.43 + : m_node (0),
16.44 + m_mtu (0xffff),
16.45 + m_name (""),
16.46 + m_ifIndex (0)
16.47 +{
16.48 + NS_LOG_FUNCTION (this);
16.49 +}
16.50 +
16.51 +void
16.52 +HostTapNetDevice::SetChannel (Ptr<TapChannel> channel)
16.53 +{
16.54 + m_channel = channel;
16.55 + m_channel->SetHostDevice (this);
16.56 +}
16.57 +
16.58 +void
16.59 +HostTapNetDevice::SetAddress (Mac48Address address)
16.60 +{
16.61 + m_address = address;
16.62 +}
16.63 +
16.64 +Mac48Address
16.65 +HostTapNetDevice::GetMacAddress (void) const
16.66 +{
16.67 + return m_address;
16.68 +}
16.69 +
16.70 +void
16.71 +HostTapNetDevice::SetName(const std::string name)
16.72 +{
16.73 + m_name = name;
16.74 +}
16.75 +std::string
16.76 +HostTapNetDevice::GetName(void) const
16.77 +{
16.78 + return m_name;
16.79 +}
16.80 +void
16.81 +HostTapNetDevice::SetIfIndex(const uint32_t index)
16.82 +{
16.83 + m_ifIndex = index;
16.84 +}
16.85 +uint32_t
16.86 +HostTapNetDevice::GetIfIndex(void) const
16.87 +{
16.88 + return m_ifIndex;
16.89 +}
16.90 +Ptr<Channel>
16.91 +HostTapNetDevice::GetChannel (void) const
16.92 +{
16.93 + return m_channel;
16.94 +}
16.95 +Address
16.96 +HostTapNetDevice::GetAddress (void) const
16.97 +{
16.98 + return m_address;
16.99 +}
16.100 +bool
16.101 +HostTapNetDevice::SetMtu (const uint16_t mtu)
16.102 +{
16.103 + m_mtu = mtu;
16.104 + return true;
16.105 +}
16.106 +uint16_t
16.107 +HostTapNetDevice::GetMtu (void) const
16.108 +{
16.109 + return m_mtu;
16.110 +}
16.111 +bool
16.112 +HostTapNetDevice::IsLinkUp (void) const
16.113 +{
16.114 + return true;
16.115 +}
16.116 +void
16.117 +HostTapNetDevice::SetLinkChangeCallback (Callback<void> callback)
16.118 +{}
16.119 +bool
16.120 +HostTapNetDevice::IsBroadcast (void) const
16.121 +{
16.122 + return true;
16.123 +}
16.124 +Address
16.125 +HostTapNetDevice::GetBroadcast (void) const
16.126 +{
16.127 + return Mac48Address ("ff:ff:ff:ff:ff:ff");
16.128 +}
16.129 +bool
16.130 +HostTapNetDevice::IsMulticast (void) const
16.131 +{
16.132 + return true;
16.133 +}
16.134 +Address
16.135 +HostTapNetDevice::GetMulticast (void) const
16.136 +{
16.137 + return Mac48Address::GetMulticastPrefix ();
16.138 +}
16.139 +Address
16.140 +HostTapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
16.141 +{
16.142 + return Mac48Address::GetMulticast (multicastGroup);
16.143 +}
16.144 +bool
16.145 +HostTapNetDevice::IsPointToPoint (void) const
16.146 +{
16.147 + return false;
16.148 +}
16.149 +bool
16.150 +HostTapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
16.151 +{
16.152 + return false;
16.153 +}
16.154 +bool
16.155 +HostTapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
16.156 +{
16.157 + return false;
16.158 +}
16.159 +Ptr<Node>
16.160 +HostTapNetDevice::GetNode (void) const
16.161 +{
16.162 + return m_node;
16.163 +}
16.164 +void
16.165 +HostTapNetDevice::SetNode (Ptr<Node> node)
16.166 +{
16.167 + m_node = node;
16.168 +}
16.169 +bool
16.170 +HostTapNetDevice::NeedsArp (void) const
16.171 +{
16.172 + return false;
16.173 +}
16.174 +void
16.175 +HostTapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
16.176 +{}
16.177 +
16.178 +void
16.179 +HostTapNetDevice::DoDispose (void)
16.180 +{
16.181 + NS_LOG_FUNCTION (this);
16.182 + m_node = 0;
16.183 + m_channel = 0;
16.184 + NetDevice::DoDispose ();
16.185 +}
16.186 +
16.187 +void
16.188 +HostTapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
16.189 +{}
16.190 +
16.191 +bool
16.192 +HostTapNetDevice::SupportsSendFrom (void) const
16.193 +{
16.194 + return false;
16.195 +}
16.196 +
16.197 +} // namespace ns3
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/src/devices/tap/host-tap-net-device.h Mon Oct 27 22:01:24 2008 -0700
17.3 @@ -0,0 +1,90 @@
17.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
17.5 +/*
17.6 + * Copyright (c) 2008 INRIA
17.7 + *
17.8 + * This program is free software; you can redistribute it and/or modify
17.9 + * it under the terms of the GNU General Public License version 2 as
17.10 + * published by the Free Software Foundation;
17.11 + *
17.12 + * This program is distributed in the hope that it will be useful,
17.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17.15 + * GNU General Public License for more details.
17.16 + *
17.17 + * You should have received a copy of the GNU General Public License
17.18 + * along with this program; if not, write to the Free Software
17.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17.20 + *
17.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
17.22 + */
17.23 +#ifndef HOST_TAP_NET_DEVICE_H
17.24 +#define HOST_TAP_NET_DEVICE_H
17.25 +
17.26 +#include "ns3/net-device.h"
17.27 +#include "ns3/mac48-address.h"
17.28 +#include "ns3/traced-callback.h"
17.29 +#include <stdint.h>
17.30 +#include <string>
17.31 +
17.32 +namespace ns3 {
17.33 +
17.34 +class Node;
17.35 +class TapChannel;
17.36 +
17.37 +
17.38 +/**
17.39 + * \ingroup netdevice
17.40 + *
17.41 + * \brief a NetDevice to get packets to and from a host tap device.
17.42 + */
17.43 +class HostTapNetDevice : public NetDevice
17.44 +{
17.45 +public:
17.46 + static TypeId GetTypeId (void);
17.47 + HostTapNetDevice ();
17.48 +
17.49 + void SetAddress (Mac48Address address);
17.50 + void SetChannel (Ptr<TapChannel> channel);
17.51 +
17.52 + Mac48Address GetMacAddress (void) const;
17.53 +
17.54 + // inherited from NetDevice base class.
17.55 + virtual void SetName(const std::string name);
17.56 + virtual std::string GetName(void) const;
17.57 + virtual void SetIfIndex(const uint32_t index);
17.58 + virtual uint32_t GetIfIndex(void) const;
17.59 + virtual Ptr<Channel> GetChannel (void) const;
17.60 + virtual Address GetAddress (void) const;
17.61 + virtual bool SetMtu (const uint16_t mtu);
17.62 + virtual uint16_t GetMtu (void) const;
17.63 + virtual bool IsLinkUp (void) const;
17.64 + virtual void SetLinkChangeCallback (Callback<void> callback);
17.65 + virtual bool IsBroadcast (void) const;
17.66 + virtual Address GetBroadcast (void) const;
17.67 + virtual bool IsMulticast (void) const;
17.68 + virtual Address GetMulticast (void) const;
17.69 + virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
17.70 + virtual bool IsPointToPoint (void) const;
17.71 + virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
17.72 + virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
17.73 + virtual Ptr<Node> GetNode (void) const;
17.74 + virtual void SetNode (Ptr<Node> node);
17.75 + virtual bool NeedsArp (void) const;
17.76 + virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
17.77 + virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
17.78 + virtual bool SupportsSendFrom (void) const;
17.79 +
17.80 +protected:
17.81 + virtual void DoDispose (void);
17.82 +private:
17.83 + Ptr<Node> m_node;
17.84 + uint16_t m_mtu;
17.85 + std::string m_name;
17.86 + uint32_t m_ifIndex;
17.87 + Mac48Address m_address;
17.88 + Ptr<TapChannel> m_channel;
17.89 +};
17.90 +
17.91 +} // namespace ns3
17.92 +
17.93 +#endif /* HOST_TAP_NET_DEVICE_H */
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/src/devices/tap/tap-channel.cc Mon Oct 27 22:01:24 2008 -0700
18.3 @@ -0,0 +1,61 @@
18.4 +#include "tap-channel.h"
18.5 +#include "host-tap-net-device.h"
18.6 +#include "tap-net-device.h"
18.7 +
18.8 +namespace ns3 {
18.9 +
18.10 +
18.11 +TapChannel::TapChannel ()
18.12 + : m_hostDevice (0),
18.13 + m_device (0)
18.14 +{}
18.15 +
18.16 +void
18.17 +TapChannel::DoDispose (void)
18.18 +{
18.19 + m_device = 0;
18.20 + m_hostDevice = 0;
18.21 + Channel::DoDispose ();
18.22 +}
18.23 +
18.24 +void
18.25 +TapChannel::SetDevice (Ptr<TapNetDevice> device)
18.26 +{
18.27 + m_device = device;
18.28 +}
18.29 +
18.30 +void
18.31 +TapChannel::SetHostDevice (Ptr<HostTapNetDevice> device)
18.32 +{
18.33 + m_hostDevice = device;
18.34 +}
18.35 +
18.36 +Ptr<HostTapNetDevice>
18.37 +TapChannel::GetHostDevice (void) const
18.38 +{
18.39 + return m_hostDevice;
18.40 +}
18.41 +
18.42 +uint32_t
18.43 +TapChannel::GetNDevices (void) const
18.44 +{
18.45 + return 2;
18.46 +}
18.47 +Ptr<NetDevice>
18.48 +TapChannel::GetDevice (uint32_t i) const
18.49 +{
18.50 + if (i == 0)
18.51 + {
18.52 + return m_device;
18.53 + }
18.54 + else if (i == 1)
18.55 + {
18.56 + return m_hostDevice;
18.57 + }
18.58 + else
18.59 + {
18.60 + return 0;
18.61 + }
18.62 +}
18.63 +
18.64 +} // namespace ns3
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/src/devices/tap/tap-channel.h Mon Oct 27 22:01:24 2008 -0700
19.3 @@ -0,0 +1,36 @@
19.4 +#ifndef TAP_CHANNEL_H
19.5 +#define TAP_CHANNEL_H
19.6 +
19.7 +#include "ns3/channel.h"
19.8 +
19.9 +namespace ns3 {
19.10 +
19.11 +class HostTapNetDevice;
19.12 +class TapNetDevice;
19.13 +class NetDevice;
19.14 +
19.15 +
19.16 +class TapChannel : public Channel
19.17 +{
19.18 +public:
19.19 + TapChannel ();
19.20 +
19.21 + void SetHostDevice (Ptr<HostTapNetDevice> device);
19.22 + void SetDevice (Ptr<TapNetDevice> device);
19.23 +
19.24 + Ptr<HostTapNetDevice> GetHostDevice (void) const;
19.25 +
19.26 + // overriden from Channel base class
19.27 + virtual uint32_t GetNDevices (void) const;
19.28 + virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
19.29 +
19.30 +private:
19.31 + virtual void DoDispose (void);
19.32 +
19.33 + Ptr<HostTapNetDevice> m_hostDevice;
19.34 + Ptr<TapNetDevice> m_device;
19.35 +};
19.36 +
19.37 +} // namespace ns3
19.38 +
19.39 +#endif /* TAP_CHANNEL_H */
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/src/devices/tap/tap-manager-client.cc Mon Oct 27 22:01:24 2008 -0700
20.3 @@ -0,0 +1,180 @@
20.4 +#include "tap-manager-client.h"
20.5 +#include "ns3/log.h"
20.6 +#include <sys/socket.h>
20.7 +#include <sys/wait.h>
20.8 +#include <sys/stat.h>
20.9 +#include <linux/un.h>
20.10 +#include <errno.h>
20.11 +#include <string.h>
20.12 +#include <iomanip>
20.13 +#include <iostream>
20.14 +#include <list>
20.15 +
20.16 +
20.17 +NS_LOG_COMPONENT_DEFINE("TapManagerClient");
20.18 +
20.19 +#define TAP_MANAGER "ns3-tap-manager"
20.20 +
20.21 +namespace ns3 {
20.22 +
20.23 +static std::string
20.24 +EncodeAsString (struct sockaddr_un un, int len)
20.25 +{
20.26 + uint8_t *buffer = (uint8_t *)&un;
20.27 + std::ostringstream oss;
20.28 + oss.setf (std::ios::hex, std::ios::basefield);
20.29 + oss.fill('0');
20.30 + for (uint8_t i = 0; i < len; i++)
20.31 + {
20.32 + oss << ":" << std::setw (2) << (uint32_t)buffer[i];
20.33 + }
20.34 + return oss.str ();
20.35 +}
20.36 +
20.37 +bool
20.38 +TapManagerClient::Exists (std::string filename) const
20.39 +{
20.40 + struct stat st;
20.41 + int retval = ::stat (filename.c_str (), &st);
20.42 + return retval == 0;
20.43 +}
20.44 +
20.45 +std::string
20.46 +TapManagerClient::FindManager (void) const
20.47 +{
20.48 + std::list<std::string> locations;
20.49 + locations.push_back ("./src/devices/tap");
20.50 + locations.push_back ("./build/debug/src/devices/tap");
20.51 + locations.push_back ("./build/optimized/src/devices/tap");
20.52 + for (std::list<std::string>::const_iterator i = locations.begin (); i != locations.end (); ++i)
20.53 + {
20.54 + if (Exists (*i + "/" + TAP_MANAGER))
20.55 + {
20.56 + return *i + "/" + TAP_MANAGER;
20.57 + }
20.58 + }
20.59 + NS_FATAL_ERROR ("Could not find manager");
20.60 + return ""; // quiet compiler
20.61 +}
20.62 +
20.63 +int
20.64 +TapManagerClient::AllocateTap (Mac48Address host, Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
20.65 +{
20.66 + NS_LOG_FUNCTION (host << ad << mask << gateway);
20.67 + // create a socket to get information back from the tap manager.
20.68 + int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
20.69 + if (sock == -1)
20.70 + {
20.71 + NS_FATAL_ERROR ("Socket creation, errno=" << strerror (errno));
20.72 + }
20.73 +
20.74 + struct sockaddr_un un;
20.75 + memset (&un, 0, sizeof (un));
20.76 + un.sun_family = AF_UNIX;
20.77 + int status = bind (sock, (struct sockaddr*)&un, sizeof (sa_family_t)); // let the kernel allocate an endpoint for us.
20.78 + if (status == -1)
20.79 + {
20.80 + NS_FATAL_ERROR ("Could not bind: errno=" << strerror (errno));
20.81 + }
20.82 + socklen_t len = sizeof (un);
20.83 + status = getsockname (sock, (struct sockaddr*)&un, &len);
20.84 + if (status == -1)
20.85 + {
20.86 + NS_FATAL_ERROR ("Could not get socket address: errno=" << strerror (errno));
20.87 + }
20.88 + NS_LOG_DEBUG ("Allocated enpoint=" << EncodeAsString (un, len) << ", len=" << len);
20.89 +
20.90 + pid_t pid = ::fork ();
20.91 + if (pid == 0)
20.92 + {
20.93 + // child.
20.94 + NS_LOG_DEBUG ("Child");
20.95 +
20.96 + std::ostringstream oss;
20.97 + oss << "--path=" << EncodeAsString (un, len);
20.98 + std::string pathArg = oss.str ();
20.99 + oss.str ("");
20.100 + oss << "--mac-addr=" << host;
20.101 + std::string hostArg = oss.str ();
20.102 + oss.str ("");
20.103 + oss << "--ip-addr=" << ad;
20.104 + std::string ipArg = oss.str ();
20.105 + oss.str ("");
20.106 + oss << "--ip-gw=" << gateway;
20.107 + std::string ipGw = oss.str ();
20.108 + oss.str ("");
20.109 + oss << "--ip-netmask=" << mask;
20.110 + std::string ipMask = oss.str ();
20.111 + oss.str ("");
20.112 + status = ::execl (FindManager ().c_str (),
20.113 + TAP_MANAGER,
20.114 + pathArg.c_str (),
20.115 + hostArg.c_str (),
20.116 + ipArg.c_str (),
20.117 + ipGw.c_str (),
20.118 + ipMask.c_str (),
20.119 + (char *)NULL);
20.120 + if (status == -1)
20.121 + {
20.122 + NS_LOG_ERROR ("Cannot execl tap-manager, errno=" << ::strerror (errno));
20.123 + }
20.124 + ::_exit (-1);
20.125 + }
20.126 + else
20.127 + {
20.128 + // parent
20.129 + NS_LOG_DEBUG ("Parent");
20.130 + int st;
20.131 + pid_t waited = waitpid (pid, &st, 0);
20.132 + if (waited == -1)
20.133 + {
20.134 + NS_FATAL_ERROR ("Cannot wait for tap-manager, errno=" << strerror (errno));
20.135 + }
20.136 + NS_ASSERT (pid == waited);
20.137 + if (!WIFEXITED (st))
20.138 + {
20.139 + // tap manager did not complete successfully
20.140 + NS_FATAL_ERROR ("tap-manager did not exit correctly");
20.141 + }
20.142 + else if (WEXITSTATUS (st) != 0)
20.143 + {
20.144 + NS_FATAL_ERROR ("tap-manager did not complete successfully, err=" << WEXITSTATUS (st));
20.145 + }
20.146 + // the tap fd should be available on our unix socket now.
20.147 + size_t msg_size = sizeof(int);
20.148 + char control[CMSG_SPACE(msg_size)];
20.149 + struct cmsghdr *cmsg;
20.150 + uint8_t buffer;
20.151 + struct iovec iov;
20.152 + iov.iov_base = &buffer;
20.153 + iov.iov_len = 1;
20.154 + struct msghdr msg;
20.155 + msg.msg_name = 0;
20.156 + msg.msg_namelen = 0;
20.157 + msg.msg_iov = &iov;
20.158 + msg.msg_iovlen = 1;
20.159 + msg.msg_control = control;
20.160 + msg.msg_controllen = sizeof (control);
20.161 + msg.msg_flags = 0;
20.162 + ssize_t bytesRead = recvmsg (sock, &msg, 0);
20.163 + if (bytesRead != 1)
20.164 + {
20.165 + NS_FATAL_ERROR ("Did not get byte from tap-manager");
20.166 + }
20.167 + NS_LOG_ERROR ("read bytes=" << bytesRead);
20.168 + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
20.169 + {
20.170 + if (cmsg->cmsg_level == SOL_SOCKET &&
20.171 + cmsg->cmsg_type == SCM_RIGHTS)
20.172 + {
20.173 + int *fd = (int*)CMSG_DATA (cmsg);
20.174 + NS_LOG_ERROR ("got tap fd=" << *fd);
20.175 + return *fd;
20.176 + }
20.177 + }
20.178 + NS_FATAL_ERROR ("Did not get SCM_RIGHTS from tap-manager");
20.179 + }
20.180 + return -1;
20.181 +}
20.182 +
20.183 +} // namespace ns3
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/src/devices/tap/tap-manager-client.h Mon Oct 27 22:01:24 2008 -0700
21.3 @@ -0,0 +1,21 @@
21.4 +#ifndef TAP_MANAGER_CLIENT_H
21.5 +#define TAP_MANAGER_CLIENT_H
21.6 +
21.7 +#include "ns3/mac48-address.h"
21.8 +#include "ns3/ipv4-address.h"
21.9 +#include <string>
21.10 +
21.11 +namespace ns3 {
21.12 +
21.13 +class TapManagerClient
21.14 +{
21.15 +public:
21.16 + int AllocateTap (Mac48Address host, Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway);
21.17 +private:
21.18 + std::string FindManager (void) const;
21.19 + bool Exists (std::string filename) const;
21.20 +};
21.21 +
21.22 +} // namespace ns3
21.23 +
21.24 +#endif /* TAP_MANAGER_CLIENT_H */
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/src/devices/tap/tap-manager.cc Mon Oct 27 22:01:24 2008 -0700
22.3 @@ -0,0 +1,362 @@
22.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
22.5 +/*
22.6 + * Copyright (c) 2008 INRIA
22.7 + *
22.8 + * This program is free software; you can redistribute it and/or modify
22.9 + * it under the terms of the GNU General Public License version 2 as
22.10 + * published by the Free Software Foundation;
22.11 + *
22.12 + * This program is distributed in the hope that it will be useful,
22.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
22.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22.15 + * GNU General Public License for more details.
22.16 + *
22.17 + * You should have received a copy of the GNU General Public License
22.18 + * along with this program; if not, write to the Free Software
22.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22.20 + *
22.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
22.22 + */
22.23 +
22.24 +#include <fcntl.h>
22.25 +#include <sys/ioctl.h>
22.26 +#include <sys/types.h>
22.27 +#include <sys/socket.h>
22.28 +#include <linux/un.h>
22.29 +#include <linux/if.h>
22.30 +#include <linux/if_tun.h>
22.31 +#include <linux/route.h>
22.32 +#include <netinet/in.h>
22.33 +#include <stdint.h>
22.34 +#include <iostream>
22.35 +#include <sstream>
22.36 +#include <iomanip>
22.37 +#include <string.h>
22.38 +#include <errno.h>
22.39 +#include <stdlib.h>
22.40 +
22.41 +#define noENABLE_LOG
22.42 +
22.43 +#define EXIT_ERROR(x, err) \
22.44 + std::cout << __FILE__ << ":" << __LINE__ << ": Unrecoverable Error: " << x; \
22.45 + std::cout << " errno=" << strerror (errno) << std::endl; \
22.46 + exit (err)
22.47 +
22.48 +#ifdef ENABLE_LOG
22.49 +#define LOG(x) \
22.50 + std::cout << x << std::endl;
22.51 +#else
22.52 +#define LOG(x)
22.53 +#endif
22.54 +
22.55 +
22.56 +#define CHECK_ARG(el,var) \
22.57 + { \
22.58 + char start[] = "--" el "="; \
22.59 + if (strncmp (*argv, start, strlen (start)) == 0) \
22.60 + { \
22.61 + var = *argv + strlen (start); \
22.62 + LOG ("--" << el << "=" << var); \
22.63 + } \
22.64 + }
22.65 +
22.66 +#define ASCII_DOT (0x2e)
22.67 +#define ASCII_ZERO (0x30)
22.68 +#define ASCII_a (0x41)
22.69 +#define ASCII_z (0x5a)
22.70 +#define ASCII_A (0x61)
22.71 +#define ASCII_Z (0x7a)
22.72 +#define ASCII_COLON (0x3a)
22.73 +#define ASCII_ZERO (0x30)
22.74 +
22.75 +static char
22.76 +AsciiToLowCase (char c)
22.77 +{
22.78 + if (c >= ASCII_a && c <= ASCII_z) {
22.79 + return c;
22.80 + } else if (c >= ASCII_A && c <= ASCII_Z) {
22.81 + return c + (ASCII_a - ASCII_A);
22.82 + } else {
22.83 + return c;
22.84 + }
22.85 +}
22.86 +
22.87 +static uint32_t
22.88 +AsciiToIpv4 (const char *address)
22.89 +{
22.90 + uint32_t host = 0;
22.91 + while (true) {
22.92 + uint8_t byte = 0;
22.93 + while (*address != ASCII_DOT &&
22.94 + *address != 0) {
22.95 + byte *= 10;
22.96 + byte += *address - ASCII_ZERO;
22.97 + address++;
22.98 + }
22.99 + host <<= 8;
22.100 + host |= byte;
22.101 + if (*address == 0) {
22.102 + break;
22.103 + }
22.104 + address++;
22.105 + }
22.106 + return host;
22.107 +}
22.108 +
22.109 +static void
22.110 +AsciiToMac48 (const char *str, uint8_t addr[6])
22.111 +{
22.112 + int i = 0;
22.113 + while (*str != 0 && i < 6)
22.114 + {
22.115 + uint8_t byte = 0;
22.116 + while (*str != ASCII_COLON && *str != 0)
22.117 + {
22.118 + byte <<= 4;
22.119 + char low = AsciiToLowCase (*str);
22.120 + if (low >= ASCII_a)
22.121 + {
22.122 + byte |= low - ASCII_a + 10;
22.123 + }
22.124 + else
22.125 + {
22.126 + byte |= low - ASCII_ZERO;
22.127 + }
22.128 + str++;
22.129 + }
22.130 + addr[i] = byte;
22.131 + i++;
22.132 + if (*str == 0)
22.133 + {
22.134 + break;
22.135 + }
22.136 + str++;
22.137 + }
22.138 +}
22.139 +
22.140 +static void
22.141 +SetInetAddress (sockaddr *ad, uint32_t networkOrder)
22.142 +{
22.143 + struct sockaddr_in *sin = (struct sockaddr_in*)ad;
22.144 + sin->sin_family = AF_INET;
22.145 + sin->sin_port = 0; // unused
22.146 + sin->sin_addr.s_addr = htonl (networkOrder);
22.147 +}
22.148 +
22.149 +
22.150 +static int
22.151 +CreateTap (const char *mac_addr, const char *ip,
22.152 + const char *gw, const char *netmask)
22.153 +{
22.154 + // opening the tun device usually requires root privs
22.155 + int tap = open ("/dev/net/tun", O_RDWR);
22.156 + if (tap == -1)
22.157 + {
22.158 + EXIT_ERROR ("Could not open /dev/net/tun", 1);
22.159 + }
22.160 + // now, crate a tap device.
22.161 + struct ifreq ifr;
22.162 + // make sure that the tap device will not send us the tun_pi header.
22.163 + ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
22.164 + ifr.ifr_name[0] = 0; // allow the kernel to pick a device name.
22.165 + int status = ioctl (tap, TUNSETIFF, (void *) &ifr);
22.166 + if (status == -1)
22.167 + {
22.168 + EXIT_ERROR ("Could not allocate a tap device", 2);
22.169 + }
22.170 + std::string tapDeviceName = (char *)ifr.ifr_name;
22.171 + LOG ("Allocated TAP device=" << tapDeviceName);
22.172 +
22.173 + // set its hardware address to something we know will be unique within the simulation
22.174 + ifr.ifr_hwaddr.sa_family = 1; // this is ARPHRD_ETHER from if_arp.h
22.175 + AsciiToMac48 (mac_addr, (uint8_t*)ifr.ifr_hwaddr.sa_data);
22.176 + status = ioctl (tap, SIOCSIFHWADDR, &ifr);
22.177 + if (status == -1)
22.178 + {
22.179 + EXIT_ERROR ("Could not set hardware address=" << mac_addr << " for=" << (char *)ifr.ifr_name, 3);
22.180 + }
22.181 + LOG ("device=" << (char *)ifr.ifr_name << " addr=" << mac_addr);
22.182 +
22.183 +
22.184 + // The ip address must be set using an AF_INET socket.
22.185 + int fd = socket (AF_INET, SOCK_DGRAM, 0);
22.186 +
22.187 + // set interface up.
22.188 + status = ioctl (fd, SIOCGIFFLAGS, &ifr);
22.189 + if (status == -1)
22.190 + {
22.191 + EXIT_ERROR ("Could not get flags for interface=" << (char *)ifr.ifr_name, 4);
22.192 + }
22.193 + ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
22.194 + status = ioctl (fd, SIOCSIFFLAGS, &ifr);
22.195 + if (status == -1)
22.196 + {
22.197 + EXIT_ERROR ("Could not bring interface " << (char *)ifr.ifr_name << " up", 5);
22.198 + }
22.199 + LOG ("device=" << (char *)ifr.ifr_name << " is up");
22.200 +
22.201 +
22.202 + // set its ip address.
22.203 + SetInetAddress (&ifr.ifr_addr, AsciiToIpv4 (ip));
22.204 + status = ioctl (fd, SIOCSIFADDR, &ifr);
22.205 + if (status == -1)
22.206 + {
22.207 + EXIT_ERROR ("Could not set ip address=" << ip << " for=" << (char *)ifr.ifr_name, 6);
22.208 + }
22.209 + LOG ("device=" << (char *)ifr.ifr_name << " addr=" << ip);
22.210 +
22.211 + // set its ip mask to be /32
22.212 + SetInetAddress (&ifr.ifr_netmask, 0xffffffff);
22.213 + status = ioctl (fd, SIOCSIFNETMASK, &ifr);
22.214 + if (status == -1)
22.215 + {
22.216 + EXIT_ERROR ("Could not set ip mask=" << netmask << " for=" << (char *)ifr.ifr_name, 7);
22.217 + }
22.218 + LOG ("device=" << (char *)ifr.ifr_name << " mask=" << netmask);
22.219 +
22.220 + // add routing entry for gateway.
22.221 + struct rtentry rt;
22.222 + SetInetAddress (&rt.rt_dst, AsciiToIpv4 (gw));
22.223 + SetInetAddress (&rt.rt_genmask, 0xffffffff);
22.224 + rt.rt_flags = RTF_UP;
22.225 + rt.rt_metric = 2;
22.226 + rt.rt_dev = (char*)tapDeviceName.c_str ();
22.227 + status = ioctl (fd, SIOCADDRT, &rt);
22.228 + if (status == -1)
22.229 + {
22.230 + EXIT_ERROR ("Could not add routing table entry", 8);
22.231 + }
22.232 + LOG ("added routing table entry for gw.");
22.233 +
22.234 + // add routing entry for subnet through gateway.
22.235 + uint32_t network = AsciiToIpv4 (ip) & AsciiToIpv4 (netmask);
22.236 + SetInetAddress (&rt.rt_dst, network);
22.237 + SetInetAddress (&rt.rt_gateway, AsciiToIpv4 (gw));
22.238 + SetInetAddress (&rt.rt_genmask, AsciiToIpv4 (netmask));
22.239 + rt.rt_flags = RTF_UP | RTF_GATEWAY;
22.240 + rt.rt_metric = 2;
22.241 + rt.rt_dev = (char*)tapDeviceName.c_str ();
22.242 + status = ioctl (fd, SIOCADDRT, &rt);
22.243 + if (status == -1)
22.244 + {
22.245 + EXIT_ERROR ("Could not add routing table entry", 9);
22.246 + }
22.247 + LOG ("added routing table entry for subnet.");
22.248 +
22.249 + return tap;
22.250 +}
22.251 +
22.252 +static struct sockaddr_un
22.253 +DecodeFromString (const char *path, socklen_t *len)
22.254 +{
22.255 + sockaddr_un un;
22.256 + uint8_t *buffer = (uint8_t *)&un;
22.257 + std::istringstream iss;
22.258 + iss.str (path);
22.259 + uint8_t n = 0;
22.260 + while (!iss.bad () && !iss.eof () && !iss.fail ())
22.261 + {
22.262 + char c;
22.263 + iss.read (&c, 1);
22.264 + uint32_t tmp;
22.265 + iss >> std::hex >> tmp;
22.266 + //LOG (std::hex << tmp);
22.267 + buffer[n] = tmp;
22.268 + n++;
22.269 + }
22.270 + *len = n;
22.271 + return un;
22.272 +}
22.273 +
22.274 +static void
22.275 +SendFd (const char *path, int fd)
22.276 +{
22.277 + // send back configuration to caller.
22.278 + int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
22.279 + if (sock == -1)
22.280 + {
22.281 + EXIT_ERROR ("Socket creation", 10);
22.282 + }
22.283 + LOG ("Socket Created");
22.284 +
22.285 + socklen_t local_len;
22.286 + struct sockaddr_un local = DecodeFromString (path, &local_len);
22.287 + LOG ("len=" << local_len);
22.288 + int status = connect (sock, (struct sockaddr*)&local, local_len);
22.289 + if (status == -1)
22.290 + {
22.291 + EXIT_ERROR ("Could not connect to caller", 11);
22.292 + }
22.293 + LOG ("Socket Connected");
22.294 +
22.295 + // we send a single byte whose content is meaningless.
22.296 + // we also return as ancillary data the tap file descriptor
22.297 + struct cmsghdr *cmsg;
22.298 + size_t msg_size = sizeof(int);
22.299 + char control[CMSG_SPACE(msg_size)];
22.300 + struct iovec iov;
22.301 + struct msghdr msg;
22.302 + char buffer = 0;
22.303 + iov.iov_base = &buffer;
22.304 + iov.iov_len = 1;
22.305 + msg.msg_name = 0;
22.306 + msg.msg_namelen = 0;
22.307 + msg.msg_iov = &iov;
22.308 + msg.msg_iovlen = 1;
22.309 + msg.msg_control = control;
22.310 + msg.msg_controllen = sizeof (control);
22.311 + msg.msg_flags = 0;
22.312 +
22.313 + cmsg = CMSG_FIRSTHDR(&msg);
22.314 + cmsg->cmsg_level = SOL_SOCKET;
22.315 + cmsg->cmsg_type = SCM_RIGHTS;
22.316 + cmsg->cmsg_len = CMSG_LEN(msg_size);
22.317 + msg.msg_controllen = cmsg->cmsg_len;
22.318 +
22.319 + int *fdptr = (int*) (CMSG_DATA(cmsg));
22.320 + *fdptr = fd;
22.321 +
22.322 + ssize_t len = sendmsg(sock, &msg, 0);
22.323 + if (len == -1)
22.324 + {
22.325 + EXIT_ERROR ("Could not send SCM_RIGHTS", 12);
22.326 + }
22.327 + LOG ("Sent SCM_RIGHTS");
22.328 +}
22.329 +
22.330 +
22.331 +
22.332 +
22.333 +int main (int argc, char *argv[])
22.334 +{
22.335 + char *path = 0;
22.336 + char *mac_addr = 0;
22.337 + char *ip_addr = 0;
22.338 + char *ip_gw = 0;
22.339 + char *ip_netmask = 0;
22.340 + char *stop = 0;
22.341 + argv++;
22.342 + argc--;
22.343 + while (argc > 0)
22.344 + {
22.345 + CHECK_ARG("path", path);
22.346 + CHECK_ARG("mac-addr", mac_addr);
22.347 + CHECK_ARG("ip-addr", ip_addr);
22.348 + CHECK_ARG("ip-gw", ip_gw);
22.349 + CHECK_ARG("ip-netmask", ip_netmask);
22.350 + CHECK_ARG("stop", stop);
22.351 + argv++;
22.352 + argc--;
22.353 + }
22.354 +
22.355 + int tap = CreateTap (mac_addr, ip_addr, ip_gw, ip_netmask);
22.356 +
22.357 + if (stop)
22.358 + {
22.359 + while (1) {}
22.360 + }
22.361 +
22.362 + SendFd (path, tap);
22.363 +
22.364 + return 0;
22.365 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/src/devices/tap/tap-net-device.cc Mon Oct 27 22:01:24 2008 -0700
23.3 @@ -0,0 +1,323 @@
23.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
23.5 +/*
23.6 + * Copyright (c) 2008 INRIA
23.7 + *
23.8 + * This program is free software; you can redistribute it and/or modify
23.9 + * it under the terms of the GNU General Public License version 2 as
23.10 + * published by the Free Software Foundation;
23.11 + *
23.12 + * This program is distributed in the hope that it will be useful,
23.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
23.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23.15 + * GNU General Public License for more details.
23.16 + *
23.17 + * You should have received a copy of the GNU General Public License
23.18 + * along with this program; if not, write to the Free Software
23.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23.20 + *
23.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
23.22 + */
23.23 +#include "tap-net-device.h"
23.24 +#include "tap-manager-client.h"
23.25 +#include "ns3/node.h"
23.26 +#include "ns3/channel.h"
23.27 +#include "ns3/packet.h"
23.28 +#include "ns3/log.h"
23.29 +#include "ns3/system-thread.h"
23.30 +#include "ns3/realtime-simulator-impl.h"
23.31 +#include "ns3/make-event.h"
23.32 +#include "ns3/simulator.h"
23.33 +#include "ns3/ethernet-header.h"
23.34 +#include "ns3/trace-source-accessor.h"
23.35 +#include "host-tap-net-device.h"
23.36 +#include "tap-channel.h"
23.37 +#include <errno.h>
23.38 +#include <stdlib.h>
23.39 +
23.40 +NS_LOG_COMPONENT_DEFINE ("TapNetDevice");
23.41 +
23.42 +namespace ns3 {
23.43 +
23.44 +TypeId
23.45 +TapNetDevice::GetTypeId (void)
23.46 +{
23.47 + static TypeId tid = TypeId ("ns3::TapNetDevice")
23.48 + .SetParent<NetDevice> ()
23.49 + .AddConstructor<TapNetDevice> ()
23.50 + .AddTraceSource ("Rx", "A packet has been received",
23.51 + MakeTraceSourceAccessor (&TapNetDevice::m_rxTrace))
23.52 + .AddTraceSource ("Tx", "A packet has been sent",
23.53 + MakeTraceSourceAccessor (&TapNetDevice::m_txTrace))
23.54 + .AddTraceSource ("Drop", "A packet has been dropped",
23.55 + MakeTraceSourceAccessor (&TapNetDevice::m_dropTrace))
23.56 + ;
23.57 + return tid;
23.58 +}
23.59 +
23.60 +TapNetDevice::TapNetDevice ()
23.61 + : m_node (0),
23.62 + m_mtu (0xffff),
23.63 + m_name (""),
23.64 + m_ifIndex (0),
23.65 + m_tap (-1)
23.66 +{
23.67 + NS_LOG_FUNCTION (this);
23.68 +}
23.69 +
23.70 +void
23.71 +TapNetDevice::SetChannel (Ptr<TapChannel> channel)
23.72 +{
23.73 + m_channel = channel;
23.74 + m_channel->SetDevice (this);
23.75 +}
23.76 +
23.77 +void
23.78 +TapNetDevice::SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
23.79 +{
23.80 + NS_LOG_FUNCTION (this << ad << mask << gateway);
23.81 + NS_ASSERT (m_tap == -1);
23.82 +
23.83 + Mac48Address hostMacAddress = m_channel->GetHostDevice ()->GetMacAddress ();
23.84 +
23.85 + TapManagerClient manager;
23.86 + m_tap = manager.AllocateTap (hostMacAddress, ad, mask, gateway);
23.87 +
23.88 + m_thread = Create<SystemThread> (MakeCallback (&TapNetDevice::ReadThread, this));
23.89 + m_thread->Start ();
23.90 +}
23.91 +
23.92 +
23.93 +void
23.94 +TapNetDevice::ReadThread (void)
23.95 +{
23.96 + NS_LOG_FUNCTION (this);
23.97 +
23.98 + while (1)
23.99 + {
23.100 + uint8_t *buffer = (uint8_t *)malloc (0xffff);
23.101 + ssize_t bytesRead = read (m_tap, buffer, 0xffff);
23.102 + if (bytesRead == -1)
23.103 + {
23.104 + if (errno == EBADF || errno == EINTR)
23.105 + {
23.106 + // the device was closed from under us by ::DoDispose
23.107 + return;
23.108 + }
23.109 + NS_FATAL_ERROR ("Error reading from tap device: errno=" << strerror (errno));
23.110 + }
23.111 + // Note: we purposedly don't use a smart pointer to manage this packet
23.112 + // because the want to hand over ownership of this packet to the ForwardUp
23.113 + // method.
23.114 + DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->
23.115 + ScheduleRealtimeNow (MakeEvent (&TapNetDevice::ForwardUp, this, buffer, (uint32_t)bytesRead));
23.116 + }
23.117 +}
23.118 +
23.119 +void
23.120 +TapNetDevice::ForwardUp (uint8_t *buffer, uint32_t size)
23.121 +{
23.122 + NS_LOG_FUNCTION (this << buffer << size);
23.123 +
23.124 + // swallow packet reference in smart pointer.
23.125 + Ptr<Packet> packet = Create<Packet> (buffer, size);
23.126 + free (buffer);
23.127 + Ptr<Packet> copy = packet->Copy ();
23.128 +
23.129 + EthernetHeader header = EthernetHeader (false);
23.130 + packet->RemoveHeader (header);
23.131 +
23.132 + uint16_t protocol = header.GetLengthType ();
23.133 + Mac48Address to = header.GetDestination ();
23.134 + Mac48Address from = header.GetSource ();
23.135 +
23.136 + NetDevice::PacketType packetType;
23.137 + if (to == m_address)
23.138 + {
23.139 + packetType = NetDevice::PACKET_HOST;
23.140 + }
23.141 + else if (to.IsBroadcast ())
23.142 + {
23.143 + packetType = NetDevice::PACKET_HOST;
23.144 + }
23.145 + else if (to.IsMulticast ())
23.146 + {
23.147 + packetType = NetDevice::PACKET_MULTICAST;
23.148 + }
23.149 + else
23.150 + {
23.151 + packetType = NetDevice::PACKET_OTHERHOST;
23.152 + }
23.153 + m_rxTrace (copy, from, to);
23.154 + if (packetType != NetDevice::PACKET_OTHERHOST)
23.155 + {
23.156 + m_rxCallback (this, packet, protocol, from);
23.157 + }
23.158 + if (!m_promiscCallback.IsNull ())
23.159 + {
23.160 + m_promiscCallback (this, packet, protocol, from, to, packetType);
23.161 + }
23.162 +}
23.163 +
23.164 +void
23.165 +TapNetDevice::SetAddress (Mac48Address address)
23.166 +{
23.167 + m_address = address;
23.168 +}
23.169 +
23.170 +void
23.171 +TapNetDevice::SetName(const std::string name)
23.172 +{
23.173 + m_name = name;
23.174 +}
23.175 +std::string
23.176 +TapNetDevice::GetName(void) const
23.177 +{
23.178 + return m_name;
23.179 +}
23.180 +void
23.181 +TapNetDevice::SetIfIndex(const uint32_t index)
23.182 +{
23.183 + m_ifIndex = index;
23.184 +}
23.185 +uint32_t
23.186 +TapNetDevice::GetIfIndex(void) const
23.187 +{
23.188 + return m_ifIndex;
23.189 +}
23.190 +Ptr<Channel>
23.191 +TapNetDevice::GetChannel (void) const
23.192 +{
23.193 + return m_channel;
23.194 +}
23.195 +Address
23.196 +TapNetDevice::GetAddress (void) const
23.197 +{
23.198 + return m_address;
23.199 +}
23.200 +bool
23.201 +TapNetDevice::SetMtu (const uint16_t mtu)
23.202 +{
23.203 + m_mtu = mtu;
23.204 + return true;
23.205 +}
23.206 +uint16_t
23.207 +TapNetDevice::GetMtu (void) const
23.208 +{
23.209 + return m_mtu;
23.210 +}
23.211 +bool
23.212 +TapNetDevice::IsLinkUp (void) const
23.213 +{
23.214 + return true;
23.215 +}
23.216 +void
23.217 +TapNetDevice::SetLinkChangeCallback (Callback<void> callback)
23.218 +{}
23.219 +bool
23.220 +TapNetDevice::IsBroadcast (void) const
23.221 +{
23.222 + return true;
23.223 +}
23.224 +Address
23.225 +TapNetDevice::GetBroadcast (void) const
23.226 +{
23.227 + return Mac48Address ("ff:ff:ff:ff:ff:ff");
23.228 +}
23.229 +bool
23.230 +TapNetDevice::IsMulticast (void) const
23.231 +{
23.232 + return true;
23.233 +}
23.234 +Address
23.235 +TapNetDevice::GetMulticast (void) const
23.236 +{
23.237 + return Mac48Address::GetMulticastPrefix ();
23.238 +}
23.239 +Address
23.240 +TapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
23.241 +{
23.242 + return Mac48Address::GetMulticast (multicastGroup);
23.243 +}
23.244 +bool
23.245 +TapNetDevice::IsPointToPoint (void) const
23.246 +{
23.247 + return false;
23.248 +}
23.249 +bool
23.250 +TapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
23.251 +{
23.252 + NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
23.253 + return SendFrom (packet, m_address, dest, protocolNumber);
23.254 +}
23.255 +bool
23.256 +TapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
23.257 +{
23.258 + NS_LOG_FUNCTION (this << packet << source << dest << protocolNumber);
23.259 + Mac48Address to = Mac48Address::ConvertFrom (dest);
23.260 + Mac48Address from = Mac48Address::ConvertFrom (source);
23.261 +
23.262 + EthernetHeader header = EthernetHeader (false);
23.263 + header.SetSource (from);
23.264 + header.SetDestination (to);
23.265 + header.SetLengthType (protocolNumber);
23.266 + packet->AddHeader (header);
23.267 +
23.268 + ssize_t written = write (m_tap, packet->PeekData (), packet->GetSize ());
23.269 + if (written == -1 || written != (ssize_t)packet->GetSize ())
23.270 + {
23.271 + m_dropTrace (packet, from, to);
23.272 + return false;
23.273 + }
23.274 +
23.275 + m_txTrace (packet, from, to);
23.276 +
23.277 + return true;
23.278 +}
23.279 +
23.280 +Ptr<Node>
23.281 +TapNetDevice::GetNode (void) const
23.282 +{
23.283 + return m_node;
23.284 +}
23.285 +void
23.286 +TapNetDevice::SetNode (Ptr<Node> node)
23.287 +{
23.288 + m_node = node;
23.289 +}
23.290 +bool
23.291 +TapNetDevice::NeedsArp (void) const
23.292 +{
23.293 + return true;
23.294 +}
23.295 +void
23.296 +TapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
23.297 +{
23.298 + m_rxCallback = cb;
23.299 +}
23.300 +
23.301 +void
23.302 +TapNetDevice::DoDispose (void)
23.303 +{
23.304 + NS_LOG_FUNCTION (this);
23.305 + close (m_tap);
23.306 + m_thread->Join ();
23.307 + m_thread = 0;
23.308 + m_node = 0;
23.309 + m_channel = 0;
23.310 + NetDevice::DoDispose ();
23.311 +}
23.312 +
23.313 +
23.314 +void
23.315 +TapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
23.316 +{
23.317 + m_promiscCallback = cb;
23.318 +}
23.319 +
23.320 +bool
23.321 +TapNetDevice::SupportsSendFrom (void) const
23.322 +{
23.323 + return true;
23.324 +}
23.325 +
23.326 +} // namespace ns3
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/src/devices/tap/tap-net-device.h Mon Oct 27 22:01:24 2008 -0700
24.3 @@ -0,0 +1,103 @@
24.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
24.5 +/*
24.6 + * Copyright (c) 2008 INRIA
24.7 + *
24.8 + * This program is free software; you can redistribute it and/or modify
24.9 + * it under the terms of the GNU General Public License version 2 as
24.10 + * published by the Free Software Foundation;
24.11 + *
24.12 + * This program is distributed in the hope that it will be useful,
24.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24.15 + * GNU General Public License for more details.
24.16 + *
24.17 + * You should have received a copy of the GNU General Public License
24.18 + * along with this program; if not, write to the Free Software
24.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24.20 + *
24.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
24.22 + */
24.23 +#ifndef TAP_NET_DEVICE_H
24.24 +#define TAP_NET_DEVICE_H
24.25 +
24.26 +#include "ns3/net-device.h"
24.27 +#include "ns3/mac48-address.h"
24.28 +#include "ns3/traced-callback.h"
24.29 +#include <stdint.h>
24.30 +#include <string>
24.31 +
24.32 +namespace ns3 {
24.33 +
24.34 +class Node;
24.35 +class SystemThread;
24.36 +class TapChannel;
24.37 +
24.38 +/**
24.39 + * \ingroup netdevice
24.40 + *
24.41 + * \brief a NetDevice to get packets to and from a host tap device.
24.42 + */
24.43 +class TapNetDevice : public NetDevice
24.44 +{
24.45 +public:
24.46 + static TypeId GetTypeId (void);
24.47 + TapNetDevice ();
24.48 +
24.49 + void SetAddress (Mac48Address address);
24.50 +
24.51 + void SetChannel (Ptr<TapChannel> channel);
24.52 +
24.53 + void SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway);
24.54 +
24.55 + // inherited from NetDevice base class.
24.56 + virtual void SetName(const std::string name);
24.57 + virtual std::string GetName(void) const;
24.58 + virtual void SetIfIndex(const uint32_t index);
24.59 + virtual uint32_t GetIfIndex(void) const;
24.60 + virtual Ptr<Channel> GetChannel (void) const;
24.61 + virtual Address GetAddress (void) const;
24.62 + virtual bool SetMtu (const uint16_t mtu);
24.63 + virtual uint16_t GetMtu (void) const;
24.64 + virtual bool IsLinkUp (void) const;
24.65 + virtual void SetLinkChangeCallback (Callback<void> callback);
24.66 + virtual bool IsBroadcast (void) const;
24.67 + virtual Address GetBroadcast (void) const;
24.68 + virtual bool IsMulticast (void) const;
24.69 + virtual Address GetMulticast (void) const;
24.70 + virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
24.71 + virtual bool IsPointToPoint (void) const;
24.72 + virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
24.73 + virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
24.74 + virtual Ptr<Node> GetNode (void) const;
24.75 + virtual void SetNode (Ptr<Node> node);
24.76 + virtual bool NeedsArp (void) const;
24.77 + virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
24.78 + virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
24.79 + virtual bool SupportsSendFrom (void) const;
24.80 +
24.81 +protected:
24.82 + virtual void DoDispose (void);
24.83 +private:
24.84 + void Receive (Ptr<Packet> packet, uint16_t protocol,
24.85 + Mac48Address to, Mac48Address from);
24.86 + void ForwardUp (uint8_t *buffer, uint32_t size);
24.87 + void ReadThread (void);
24.88 +
24.89 + NetDevice::ReceiveCallback m_rxCallback;
24.90 + NetDevice::PromiscReceiveCallback m_promiscCallback;
24.91 + Ptr<Node> m_node;
24.92 + uint16_t m_mtu;
24.93 + std::string m_name;
24.94 + uint32_t m_ifIndex;
24.95 + Mac48Address m_address;
24.96 + int m_tap;
24.97 + Ptr<SystemThread> m_thread;
24.98 + TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_rxTrace;
24.99 + TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_txTrace;
24.100 + TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_dropTrace;
24.101 + Ptr<TapChannel> m_channel;
24.102 +};
24.103 +
24.104 +} // namespace ns3
24.105 +
24.106 +#endif /* TAP_NET_DEVICE_H */
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/src/devices/tap/wscript Mon Oct 27 22:01:24 2008 -0700
25.3 @@ -0,0 +1,26 @@
25.4 +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
25.5 +
25.6 +
25.7 +def build(bld):
25.8 + obj = bld.create_suid_program('ns3-tap-manager')
25.9 + obj.source = [
25.10 + 'tap-manager.cc',
25.11 + ]
25.12 +
25.13 + module = bld.create_ns3_module('tap', ['node'])
25.14 + module.uselib = 'CAP'
25.15 + module.source = [
25.16 + 'tap-net-device.cc',
25.17 + 'tap-manager-client.cc',
25.18 + 'tap-channel.cc',
25.19 + 'host-tap-net-device.cc',
25.20 + ]
25.21 + headers = bld.create_obj('ns3header')
25.22 + headers.module = 'tap'
25.23 + headers.source = [
25.24 + 'tap-net-device.h',
25.25 + 'host-tap-net-device.h',
25.26 + 'tap-channel.h',
25.27 + ]
25.28 +
25.29 +
26.1 --- a/src/node/net-device.h Mon Oct 27 13:01:28 2008 -0700
26.2 +++ b/src/node/net-device.h Mon Oct 27 22:01:24 2008 -0700
26.3 @@ -255,13 +255,23 @@
26.4 virtual bool NeedsArp (void) const = 0;
26.5
26.6
26.7 - /** Packet types */
26.8 + /**
26.9 + * Packet types are used as they are in Linux. GCC name resolution on
26.10 + * typedef enum {} PacketType is broken for the foreseeable future, so
26.11 + * if you need to use ns-3 PacketType in a driver that also uses the
26.12 + * Linux packet types you're hosed unless we define a shadow type,
26.13 + * which we do here.
26.14 + */
26.15 enum PacketType
26.16 {
26.17 - PACKET_HOST = 1, /* To us */
26.18 - PACKET_BROADCAST, /* To all */
26.19 - PACKET_MULTICAST, /* To group */
26.20 - PACKET_OTHERHOST, /* To someone else */
26.21 + PACKET_HOST = 1, /**< Packet addressed oo us */
26.22 + NS3_PACKET_HOST = PACKET_HOST,
26.23 + PACKET_BROADCAST, /**< Packet addressed to all */
26.24 + NS3_PACKET_BROADCAST = PACKET_BROADCAST,
26.25 + PACKET_MULTICAST, /**< Packet addressed to multicast group */
26.26 + NS3_PACKET_MULTICAST = PACKET_MULTICAST,
26.27 + PACKET_OTHERHOST, /**< Packet addressed to someone else */
26.28 + NS3_PACKET_OTHERHOST = PACKET_OTHERHOST,
26.29 };
26.30
26.31 /**
27.1 --- a/src/wscript Mon Oct 27 13:01:28 2008 -0700
27.2 +++ b/src/wscript Mon Oct 27 22:01:24 2008 -0700
27.3 @@ -20,7 +20,8 @@
27.4 'devices/point-to-point',
27.5 'devices/csma',
27.6 'devices/bridge',
27.7 - 'devices/emutap',
27.8 + 'devices/tap',
27.9 + 'devices/emulated',
27.10 'applications/onoff',
27.11 'applications/packet-sink',
27.12 'applications/udp-echo',