src/devices/emutap/tap-net-device.cc
changeset 3826 40c5841b616d
equal deleted inserted replaced
3817:4ed410f69d36 3826:40c5841b616d
       
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2008 INRIA
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License version 2 as
       
     7  * published by the Free Software Foundation;
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    17  *
       
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
       
    19  */
       
    20 #include "tap-net-device.h"
       
    21 #include "tap-manager-client.h"
       
    22 #include "ns3/node.h"
       
    23 #include "ns3/channel.h"
       
    24 #include "ns3/packet.h"
       
    25 #include "ns3/log.h"
       
    26 #include "ns3/system-thread.h"
       
    27 #include "ns3/realtime-simulator-impl.h"
       
    28 #include "ns3/make-event.h"
       
    29 #include "ns3/simulator.h"
       
    30 #include "ns3/ethernet-header.h"
       
    31 #include "ns3/trace-source-accessor.h"
       
    32 #include "host-tap-net-device.h"
       
    33 #include "tap-channel.h"
       
    34 #include <errno.h>
       
    35 #include <stdlib.h>
       
    36 
       
    37 NS_LOG_COMPONENT_DEFINE ("TapNetDevice");
       
    38 
       
    39 namespace ns3 {
       
    40 
       
    41 TypeId 
       
    42 TapNetDevice::GetTypeId (void)
       
    43 {
       
    44   static TypeId tid = TypeId ("ns3::TapNetDevice")
       
    45     .SetParent<NetDevice> ()
       
    46     .AddConstructor<TapNetDevice> ()
       
    47     .AddTraceSource ("Rx", "A packet has been received",
       
    48                      MakeTraceSourceAccessor (&TapNetDevice::m_rxTrace))
       
    49     .AddTraceSource ("Tx", "A packet has been sent",
       
    50                      MakeTraceSourceAccessor (&TapNetDevice::m_txTrace))
       
    51     .AddTraceSource ("Drop", "A packet has been dropped",
       
    52                      MakeTraceSourceAccessor (&TapNetDevice::m_dropTrace))
       
    53     ;
       
    54   return tid;
       
    55 }
       
    56 
       
    57 TapNetDevice::TapNetDevice ()
       
    58   : m_node (0),
       
    59     m_mtu (0xffff),
       
    60     m_name (""),
       
    61     m_ifIndex (0),
       
    62     m_tap (-1)
       
    63 {
       
    64   NS_LOG_FUNCTION (this);
       
    65 }
       
    66 
       
    67 void 
       
    68 TapNetDevice::SetChannel (Ptr<TapChannel> channel)
       
    69 {
       
    70   m_channel = channel;
       
    71   m_channel->SetDevice (this);
       
    72 }
       
    73 
       
    74 void 
       
    75 TapNetDevice::SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
       
    76 {
       
    77   NS_LOG_FUNCTION (this << ad << mask << gateway);
       
    78   NS_ASSERT (m_tap == -1);
       
    79 
       
    80   Mac48Address hostMacAddress = m_channel->GetHostDevice ()->GetMacAddress ();
       
    81 
       
    82   TapManagerClient manager;
       
    83   m_tap = manager.AllocateTap (hostMacAddress, ad, mask, gateway);
       
    84 
       
    85   m_thread = Create<SystemThread> (MakeCallback (&TapNetDevice::ReadThread, this));
       
    86   m_thread->Start ();
       
    87 }
       
    88 
       
    89 
       
    90 void
       
    91 TapNetDevice::ReadThread (void)
       
    92 {
       
    93   NS_LOG_FUNCTION (this);
       
    94 
       
    95   while (1)
       
    96     {
       
    97       uint8_t *buffer = (uint8_t *)malloc (0xffff);
       
    98       ssize_t bytesRead = read (m_tap, buffer, 0xffff);
       
    99       if (bytesRead == -1)
       
   100         {
       
   101           if (errno == EBADF || errno == EINTR)
       
   102             {
       
   103               // the device was closed from under us by ::DoDispose
       
   104               return;
       
   105             }
       
   106           NS_FATAL_ERROR ("Error reading from tap device: errno=" << strerror (errno));
       
   107         }
       
   108       // Note: we purposedly don't use a smart pointer to manage this packet
       
   109       // because the want to hand over ownership of this packet to the ForwardUp
       
   110       // method.
       
   111       DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->
       
   112         ScheduleRealtimeNow (MakeEvent (&TapNetDevice::ForwardUp, this, buffer, (uint32_t)bytesRead));
       
   113     }
       
   114 }
       
   115 
       
   116 void
       
   117 TapNetDevice::ForwardUp (uint8_t *buffer, uint32_t size)
       
   118 {
       
   119   NS_LOG_FUNCTION (this << buffer << size);
       
   120 
       
   121   // swallow packet reference in smart pointer.
       
   122   Ptr<Packet> packet = Create<Packet> (buffer, size);
       
   123   free (buffer);
       
   124   Ptr<Packet> copy = packet->Copy ();
       
   125 
       
   126   EthernetHeader header = EthernetHeader (false);
       
   127   packet->RemoveHeader (header);
       
   128 
       
   129   uint16_t protocol = header.GetLengthType ();
       
   130   Mac48Address to = header.GetDestination ();
       
   131   Mac48Address from = header.GetSource ();
       
   132   
       
   133   NetDevice::PacketType packetType;
       
   134   if (to == m_address)
       
   135     {
       
   136       packetType = NetDevice::PACKET_HOST;
       
   137     }
       
   138   else if (to.IsBroadcast ())
       
   139     {
       
   140       packetType = NetDevice::PACKET_HOST;
       
   141     }
       
   142   else if (to.IsMulticast ())
       
   143     {
       
   144       packetType = NetDevice::PACKET_MULTICAST;
       
   145     }
       
   146   else 
       
   147     {
       
   148       packetType = NetDevice::PACKET_OTHERHOST;
       
   149     }
       
   150   m_rxTrace (copy, from, to);
       
   151   if (packetType != NetDevice::PACKET_OTHERHOST)
       
   152     {
       
   153       m_rxCallback (this, packet, protocol, from);
       
   154     }
       
   155   if (!m_promiscCallback.IsNull ())
       
   156     {
       
   157       m_promiscCallback (this, packet, protocol, from, to, packetType);
       
   158     }
       
   159 }
       
   160 
       
   161 void 
       
   162 TapNetDevice::SetAddress (Mac48Address address)
       
   163 {
       
   164   m_address = address;
       
   165 }
       
   166 
       
   167 void 
       
   168 TapNetDevice::SetName(const std::string name)
       
   169 {
       
   170   m_name = name;
       
   171 }
       
   172 std::string 
       
   173 TapNetDevice::GetName(void) const
       
   174 {
       
   175   return m_name;
       
   176 }
       
   177 void 
       
   178 TapNetDevice::SetIfIndex(const uint32_t index)
       
   179 {
       
   180   m_ifIndex = index;
       
   181 }
       
   182 uint32_t 
       
   183 TapNetDevice::GetIfIndex(void) const
       
   184 {
       
   185   return m_ifIndex;
       
   186 }
       
   187 Ptr<Channel> 
       
   188 TapNetDevice::GetChannel (void) const
       
   189 {
       
   190   return m_channel;
       
   191 }
       
   192 Address 
       
   193 TapNetDevice::GetAddress (void) const
       
   194 {
       
   195   return m_address;
       
   196 }
       
   197 bool 
       
   198 TapNetDevice::SetMtu (const uint16_t mtu)
       
   199 {
       
   200   m_mtu = mtu;
       
   201   return true;
       
   202 }
       
   203 uint16_t 
       
   204 TapNetDevice::GetMtu (void) const
       
   205 {
       
   206   return m_mtu;
       
   207 }
       
   208 bool 
       
   209 TapNetDevice::IsLinkUp (void) const
       
   210 {
       
   211   return true;
       
   212 }
       
   213 void 
       
   214 TapNetDevice::SetLinkChangeCallback (Callback<void> callback)
       
   215 {}
       
   216 bool 
       
   217 TapNetDevice::IsBroadcast (void) const
       
   218 {
       
   219   return true;
       
   220 }
       
   221 Address
       
   222 TapNetDevice::GetBroadcast (void) const
       
   223 {
       
   224   return Mac48Address ("ff:ff:ff:ff:ff:ff");
       
   225 }
       
   226 bool 
       
   227 TapNetDevice::IsMulticast (void) const
       
   228 {
       
   229   return true;
       
   230 }
       
   231 Address 
       
   232 TapNetDevice::GetMulticast (void) const
       
   233 {
       
   234   return Mac48Address::GetMulticastPrefix ();
       
   235 }
       
   236 Address 
       
   237 TapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
       
   238 {
       
   239   return Mac48Address::GetMulticast (multicastGroup);
       
   240 }
       
   241 bool 
       
   242 TapNetDevice::IsPointToPoint (void) const
       
   243 {
       
   244   return false;
       
   245 }
       
   246 bool 
       
   247 TapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
       
   248 {
       
   249   NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
       
   250   return SendFrom (packet, m_address, dest, protocolNumber);
       
   251 }
       
   252 bool 
       
   253 TapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
       
   254 {
       
   255   NS_LOG_FUNCTION (this << packet << source << dest << protocolNumber);
       
   256   Mac48Address to = Mac48Address::ConvertFrom (dest);
       
   257   Mac48Address from = Mac48Address::ConvertFrom (source);
       
   258 
       
   259   EthernetHeader header = EthernetHeader (false);
       
   260   header.SetSource (from);
       
   261   header.SetDestination (to);
       
   262   header.SetLengthType (protocolNumber);
       
   263   packet->AddHeader (header);
       
   264 
       
   265   ssize_t written = write (m_tap, packet->PeekData (), packet->GetSize ());
       
   266   if (written == -1 || written != (ssize_t)packet->GetSize ())
       
   267     {
       
   268       m_dropTrace (packet, from, to);
       
   269       return false;
       
   270     }
       
   271 
       
   272   m_txTrace (packet, from, to);
       
   273   
       
   274   return true;
       
   275 }
       
   276 
       
   277 Ptr<Node> 
       
   278 TapNetDevice::GetNode (void) const
       
   279 {
       
   280   return m_node;
       
   281 }
       
   282 void 
       
   283 TapNetDevice::SetNode (Ptr<Node> node)
       
   284 {
       
   285   m_node = node;
       
   286 }
       
   287 bool 
       
   288 TapNetDevice::NeedsArp (void) const
       
   289 {
       
   290   return true;
       
   291 }
       
   292 void 
       
   293 TapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
       
   294 {
       
   295   m_rxCallback = cb;
       
   296 }
       
   297 
       
   298 void
       
   299 TapNetDevice::DoDispose (void)
       
   300 {
       
   301   NS_LOG_FUNCTION (this);
       
   302   close (m_tap);
       
   303   m_thread->Join ();
       
   304   m_thread = 0;
       
   305   m_node = 0;
       
   306   m_channel = 0;
       
   307   NetDevice::DoDispose ();
       
   308 }
       
   309 
       
   310 
       
   311 void
       
   312 TapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
       
   313 {
       
   314   m_promiscCallback = cb;
       
   315 }
       
   316 
       
   317 bool
       
   318 TapNetDevice::SupportsSendFrom (void) const
       
   319 {
       
   320   return true;
       
   321 }
       
   322 
       
   323 } // namespace ns3