src/devices/bridge/bridge-net-device.cc
author vincent@clarinet.u-strasbg.fr
Fri Nov 07 11:36:15 2008 -0800 (2008-11-07)
changeset 3852 9cf7ad0cac85
parent 3841 1e7abf5fca79
child 3936 e525995ce5dc
permissions -rw-r--r--
Initial IPv6 capability
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * This program is free software; you can redistribute it and/or modify
     4  * it under the terms of the GNU General Public License version 2 as
     5  * published by the Free Software Foundation;
     6  *
     7  * This program is distributed in the hope that it will be useful,
     8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    10  * GNU General Public License for more details.
    11  *
    12  * You should have received a copy of the GNU General Public License
    13  * along with this program; if not, write to the Free Software
    14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    15  *
    16  * Author: Gustavo Carneiro  <gjc@inescporto.pt>
    17  */
    18 #include "bridge-net-device.h"
    19 #include "ns3/node.h"
    20 #include "ns3/channel.h"
    21 #include "ns3/packet.h"
    22 #include "ns3/log.h"
    23 #include "ns3/boolean.h"
    24 #include "ns3/simulator.h"
    25 
    26 NS_LOG_COMPONENT_DEFINE ("BridgeNetDevice");
    27 
    28 namespace ns3 {
    29 
    30 NS_OBJECT_ENSURE_REGISTERED (BridgeNetDevice);
    31 
    32 
    33 TypeId
    34 BridgeNetDevice::GetTypeId (void)
    35 {
    36   static TypeId tid = TypeId ("ns3::BridgeNetDevice")
    37     .SetParent<NetDevice> ()
    38     .AddConstructor<BridgeNetDevice> ()
    39     .AddAttribute ("EnableLearning",
    40                    "Enable the learning mode of the Learning Bridge",
    41                    BooleanValue (true),
    42                    MakeBooleanAccessor (&BridgeNetDevice::m_enableLearning),
    43                    MakeBooleanChecker ())
    44     .AddAttribute ("ExpirationTime",
    45                    "Time it takes for learned MAC state entry to expire.",
    46                    TimeValue (Seconds (30)),
    47                    MakeTimeAccessor (&BridgeNetDevice::m_expirationTime),
    48                    MakeTimeChecker ())
    49     ;
    50   return tid;
    51 }
    52 
    53 
    54 BridgeNetDevice::BridgeNetDevice ()
    55   : m_node (0),
    56     m_name (""),
    57     m_ifIndex (0),
    58     m_mtu (0xffff)
    59 {
    60   m_channel = CreateObject<BridgeChannel> ();
    61 }
    62 
    63 void
    64 BridgeNetDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet, uint16_t protocol,
    65                                     Address const &src, Address const &dst, PacketType packetType)
    66 {
    67   NS_LOG_FUNCTION_NOARGS ();
    68   NS_LOG_DEBUG ("UID is " << packet->GetUid ());
    69 
    70   Mac48Address src48 = Mac48Address::ConvertFrom (src);
    71   Mac48Address dst48 = Mac48Address::ConvertFrom (dst);
    72 
    73   if (!m_promiscRxCallback.IsNull ())
    74     {
    75       m_promiscRxCallback (this, packet, protocol, src, dst, packetType);
    76     }
    77 
    78   switch (packetType)
    79     {
    80     case PACKET_HOST:
    81       if (dst48 == m_address)
    82         {
    83           m_rxCallback (this, packet, protocol, src);
    84         }
    85       break;
    86 
    87     case PACKET_BROADCAST:
    88     case PACKET_MULTICAST:
    89       m_rxCallback (this, packet, protocol, src);
    90       ForwardBroadcast (incomingPort, packet, protocol, src48, dst48);
    91       break;
    92 
    93     case PACKET_OTHERHOST:
    94       ForwardUnicast (incomingPort, packet, protocol, src48, dst48);
    95       break;
    96     }
    97 }
    98 
    99 void
   100 BridgeNetDevice::ForwardUnicast (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
   101                                  uint16_t protocol, Mac48Address src, Mac48Address dst)
   102 {
   103   NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
   104                 << ", packet=" << packet << ", protocol="<<protocol
   105                 << ", src=" << src << ", dst=" << dst << ")");
   106 
   107   Learn (src, incomingPort);
   108   Ptr<NetDevice> outPort = GetLearnedState (dst);
   109   if (outPort != NULL && outPort != incomingPort)
   110     {
   111       NS_LOG_LOGIC ("Learning bridge state says to use port `" << outPort->GetName () << "'");
   112       outPort->SendFrom (packet->Copy (), src, dst, protocol);
   113     }
   114   else
   115     {
   116       NS_LOG_LOGIC ("No learned state: send through all ports");
   117       for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
   118            iter != m_ports.end (); iter++)
   119         {
   120           Ptr<NetDevice> port = *iter;
   121           if (port != incomingPort)
   122             {
   123               NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " << incomingPort->GetName ()
   124                             << " --> " << port->GetName ()
   125                             << " (UID " << packet->GetUid () << ").");
   126               port->SendFrom (packet->Copy (), src, dst, protocol);
   127             }
   128         }
   129     }
   130 }
   131 
   132 void
   133 BridgeNetDevice::ForwardBroadcast (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
   134                                         uint16_t protocol, Mac48Address src, Mac48Address dst)
   135 {
   136   NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
   137                 << ", packet=" << packet << ", protocol="<<protocol
   138                 << ", src=" << src << ", dst=" << dst << ")");
   139   Learn (src, incomingPort);
   140 
   141   for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
   142          iter != m_ports.end (); iter++)
   143     {
   144       Ptr<NetDevice> port = *iter;
   145       if (port != incomingPort)
   146         {
   147           NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " << incomingPort->GetName ()
   148                         << " --> " << port->GetName ()
   149                         << " (UID " << packet->GetUid () << ").");
   150           port->SendFrom (packet->Copy (), src, dst, protocol);
   151         }
   152     }
   153 }
   154 
   155 void BridgeNetDevice::Learn (Mac48Address source, Ptr<NetDevice> port)
   156 {
   157   if (m_enableLearning)
   158     {
   159       LearnedState &state = m_learnState[source];
   160       state.associatedPort = port;
   161       state.expirationTime = Simulator::Now () + m_expirationTime;
   162     }
   163 }
   164 
   165 Ptr<NetDevice> BridgeNetDevice::GetLearnedState (Mac48Address source)
   166 {
   167   if (m_enableLearning)
   168     {
   169       Time now = Simulator::Now ();
   170       std::map<Mac48Address, LearnedState>::iterator iter =
   171         m_learnState.find (source);
   172       if (iter != m_learnState.end ())
   173         {
   174           LearnedState &state = iter->second;
   175           if (state.expirationTime > now)
   176             {
   177               return state.associatedPort;
   178             }
   179           else
   180             {
   181               m_learnState.erase (iter);
   182             }
   183         }
   184     }
   185   return NULL;
   186 }
   187 
   188 void 
   189 BridgeNetDevice::AddBridgePort (Ptr<NetDevice> bridgePort)
   190 {
   191   NS_ASSERT (bridgePort != this);
   192   if (!Mac48Address::IsMatchingType (bridgePort->GetAddress ()))
   193     {
   194       NS_FATAL_ERROR ("Device does not support eui 48 addresses: cannot be added to bridge.");
   195     }
   196   if (!bridgePort->SupportsSendFrom ())
   197     {
   198       NS_FATAL_ERROR ("Device does not support SendFrom: cannot be added to bridge.");
   199     }
   200   if (m_address == Mac48Address ())
   201     {
   202       m_address = Mac48Address::ConvertFrom (bridgePort->GetAddress ());
   203     }
   204 
   205   NS_LOG_DEBUG ("RegisterProtocolHandler for " << bridgePort->GetName ());
   206   m_node->RegisterProtocolHandler (MakeCallback (&BridgeNetDevice::ReceiveFromDevice, this),
   207                                    0, bridgePort, true);
   208   m_ports.push_back (bridgePort);
   209   m_channel->AddChannel (bridgePort->GetChannel ());
   210 }
   211 
   212 void 
   213 BridgeNetDevice::SetName(const std::string name)
   214 {
   215   m_name = name;
   216 }
   217 
   218 std::string 
   219 BridgeNetDevice::GetName(void) const
   220 {
   221   return m_name;
   222 }
   223 
   224 void 
   225 BridgeNetDevice::SetIfIndex(const uint32_t index)
   226 {
   227   m_ifIndex = index;
   228 }
   229 
   230 uint32_t 
   231 BridgeNetDevice::GetIfIndex(void) const
   232 {
   233   return m_ifIndex;
   234 }
   235 
   236 Ptr<Channel> 
   237 BridgeNetDevice::GetChannel (void) const
   238 {
   239   return m_channel;
   240 }
   241 
   242 Address 
   243 BridgeNetDevice::GetAddress (void) const
   244 {
   245   return m_address;
   246 }
   247 
   248 bool 
   249 BridgeNetDevice::SetMtu (const uint16_t mtu)
   250 {
   251   m_mtu = mtu;
   252   return true;
   253 }
   254 
   255 uint16_t 
   256 BridgeNetDevice::GetMtu (void) const
   257 {
   258   return m_mtu;
   259 }
   260 
   261 
   262 bool 
   263 BridgeNetDevice::IsLinkUp (void) const
   264 {
   265   return true;
   266 }
   267 
   268 
   269 void 
   270 BridgeNetDevice::SetLinkChangeCallback (Callback<void> callback)
   271 {}
   272 
   273 
   274 bool 
   275 BridgeNetDevice::IsBroadcast (void) const
   276 {
   277   return true;
   278 }
   279 
   280 
   281 Address
   282 BridgeNetDevice::GetBroadcast (void) const
   283 {
   284   return Mac48Address ("ff:ff:ff:ff:ff:ff");
   285 }
   286 
   287 bool
   288 BridgeNetDevice::IsMulticast (void) const
   289 {
   290   return true;
   291 }
   292 
   293 Address
   294 BridgeNetDevice::GetMulticast (Ipv4Address multicastGroup) const
   295 {
   296  NS_LOG_FUNCTION (this << multicastGroup);
   297  Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
   298  return multicast;
   299 }
   300 
   301 
   302 bool 
   303 BridgeNetDevice::IsPointToPoint (void) const
   304 {
   305   return false;
   306 }
   307 
   308 
   309 bool 
   310 BridgeNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
   311 {
   312   for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
   313          iter != m_ports.end (); iter++)
   314     {
   315       Ptr<NetDevice> port = *iter;
   316       port->SendFrom (packet, m_address, dest, protocolNumber);
   317     }
   318 
   319   return true;
   320 }
   321 
   322 bool 
   323 BridgeNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
   324 {
   325   for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
   326          iter != m_ports.end (); iter++)
   327     {
   328       Ptr<NetDevice> port = *iter;
   329       port->SendFrom (packet, src, dest, protocolNumber);
   330     }
   331 
   332   return true;
   333 }
   334 
   335 
   336 Ptr<Node> 
   337 BridgeNetDevice::GetNode (void) const
   338 {
   339   return m_node;
   340 }
   341 
   342 
   343 void 
   344 BridgeNetDevice::SetNode (Ptr<Node> node)
   345 {
   346   m_node = node;
   347 }
   348 
   349 
   350 bool 
   351 BridgeNetDevice::NeedsArp (void) const
   352 {
   353   return true;
   354 }
   355 
   356 
   357 void 
   358 BridgeNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
   359 {
   360   m_rxCallback = cb;
   361 }
   362 
   363 void 
   364 BridgeNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
   365 {
   366   m_promiscRxCallback = cb;
   367 }
   368 
   369 bool
   370 BridgeNetDevice::SupportsSendFrom () const
   371 {
   372   return true;
   373 }
   374 
   375 
   376 void
   377 BridgeNetDevice::DoDispose (void)
   378 {
   379   m_node = 0;
   380   NetDevice::DoDispose ();
   381 }
   382 
   383 Address BridgeNetDevice::GetMulticast (Ipv6Address addr) const
   384 {
   385   NS_LOG_FUNCTION (this << addr);
   386   return Mac48Address::GetMulticast (addr);
   387 }
   388 
   389 } // namespace ns3