A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
bridge-net-device.cc
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 #include "ns3/uinteger.h"
26 
27 NS_LOG_COMPONENT_DEFINE ("BridgeNetDevice");
28 
29 namespace ns3 {
30 
31 NS_OBJECT_ENSURE_REGISTERED (BridgeNetDevice);
32 
33 
34 TypeId
35 BridgeNetDevice::GetTypeId (void)
36 {
37  static TypeId tid = TypeId ("ns3::BridgeNetDevice")
38  .SetParent<NetDevice> ()
39  .AddConstructor<BridgeNetDevice> ()
40  .AddAttribute ("Mtu", "The MAC-level Maximum Transmission Unit",
41  UintegerValue (1500),
42  MakeUintegerAccessor (&BridgeNetDevice::SetMtu,
44  MakeUintegerChecker<uint16_t> ())
45  .AddAttribute ("EnableLearning",
46  "Enable the learning mode of the Learning Bridge",
47  BooleanValue (true),
48  MakeBooleanAccessor (&BridgeNetDevice::m_enableLearning),
49  MakeBooleanChecker ())
50  .AddAttribute ("ExpirationTime",
51  "Time it takes for learned MAC state entry to expire.",
52  TimeValue (Seconds (300)),
53  MakeTimeAccessor (&BridgeNetDevice::m_expirationTime),
54  MakeTimeChecker ())
55  ;
56  return tid;
57 }
58 
59 
60 BridgeNetDevice::BridgeNetDevice ()
61  : m_node (0),
62  m_ifIndex (0)
63 {
65  m_channel = CreateObject<BridgeChannel> ();
66 }
67 
68 BridgeNetDevice::~BridgeNetDevice()
69 {
71 }
72 
73 void
75 {
77  for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin (); iter != m_ports.end (); iter++)
78  {
79  *iter = 0;
80  }
81  m_ports.clear ();
82  m_channel = 0;
83  m_node = 0;
85 }
86 
87 void
88 BridgeNetDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet, uint16_t protocol,
89  Address const &src, Address const &dst, PacketType packetType)
90 {
92  NS_LOG_DEBUG ("UID is " << packet->GetUid ());
93 
96 
97  if (!m_promiscRxCallback.IsNull ())
98  {
99  m_promiscRxCallback (this, packet, protocol, src, dst, packetType);
100  }
101 
102  switch (packetType)
103  {
104  case PACKET_HOST:
105  if (dst48 == m_address)
106  {
107  m_rxCallback (this, packet, protocol, src);
108  }
109  break;
110 
111  case PACKET_BROADCAST:
112  case PACKET_MULTICAST:
113  m_rxCallback (this, packet, protocol, src);
114  ForwardBroadcast (incomingPort, packet, protocol, src48, dst48);
115  break;
116 
117  case PACKET_OTHERHOST:
118  if (dst48 == m_address)
119  {
120  m_rxCallback (this, packet, protocol, src);
121  }
122  else
123  {
124  ForwardUnicast (incomingPort, packet, protocol, src48, dst48);
125  }
126  break;
127  }
128 }
129 
130 void
131 BridgeNetDevice::ForwardUnicast (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
132  uint16_t protocol, Mac48Address src, Mac48Address dst)
133 {
135  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetInstanceTypeId ().GetName ()
136  << ", packet=" << packet << ", protocol="<<protocol
137  << ", src=" << src << ", dst=" << dst << ")");
138 
139  Learn (src, incomingPort);
140  Ptr<NetDevice> outPort = GetLearnedState (dst);
141  if (outPort != NULL && outPort != incomingPort)
142  {
143  NS_LOG_LOGIC ("Learning bridge state says to use port `" << outPort->GetInstanceTypeId ().GetName () << "'");
144  outPort->SendFrom (packet->Copy (), src, dst, protocol);
145  }
146  else
147  {
148  NS_LOG_LOGIC ("No learned state: send through all ports");
149  for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
150  iter != m_ports.end (); iter++)
151  {
152  Ptr<NetDevice> port = *iter;
153  if (port != incomingPort)
154  {
155  NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): "
156  << incomingPort->GetInstanceTypeId ().GetName ()
157  << " --> " << port->GetInstanceTypeId ().GetName ()
158  << " (UID " << packet->GetUid () << ").");
159  port->SendFrom (packet->Copy (), src, dst, protocol);
160  }
161  }
162  }
163 }
164 
165 void
166 BridgeNetDevice::ForwardBroadcast (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
167  uint16_t protocol, Mac48Address src, Mac48Address dst)
168 {
170  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetInstanceTypeId ().GetName ()
171  << ", packet=" << packet << ", protocol="<<protocol
172  << ", src=" << src << ", dst=" << dst << ")");
173  Learn (src, incomingPort);
174 
175  for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
176  iter != m_ports.end (); iter++)
177  {
178  Ptr<NetDevice> port = *iter;
179  if (port != incomingPort)
180  {
181  NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): "
182  << incomingPort->GetInstanceTypeId ().GetName ()
183  << " --> " << port->GetInstanceTypeId ().GetName ()
184  << " (UID " << packet->GetUid () << ").");
185  port->SendFrom (packet->Copy (), src, dst, protocol);
186  }
187  }
188 }
189 
190 void BridgeNetDevice::Learn (Mac48Address source, Ptr<NetDevice> port)
191 {
193  if (m_enableLearning)
194  {
195  LearnedState &state = m_learnState[source];
196  state.associatedPort = port;
197  state.expirationTime = Simulator::Now () + m_expirationTime;
198  }
199 }
200 
201 Ptr<NetDevice> BridgeNetDevice::GetLearnedState (Mac48Address source)
202 {
204  if (m_enableLearning)
205  {
206  Time now = Simulator::Now ();
207  std::map<Mac48Address, LearnedState>::iterator iter =
208  m_learnState.find (source);
209  if (iter != m_learnState.end ())
210  {
211  LearnedState &state = iter->second;
212  if (state.expirationTime > now)
213  {
214  return state.associatedPort;
215  }
216  else
217  {
218  m_learnState.erase (iter);
219  }
220  }
221  }
222  return NULL;
223 }
224 
225 uint32_t
226 BridgeNetDevice::GetNBridgePorts (void) const
227 {
229  return m_ports.size ();
230 }
231 
232 
233 Ptr<NetDevice>
234 BridgeNetDevice::GetBridgePort (uint32_t n) const
235 {
237  return m_ports[n];
238 }
239 
240 void
242 {
244  NS_ASSERT (bridgePort != this);
245  if (!Mac48Address::IsMatchingType (bridgePort->GetAddress ()))
246  {
247  NS_FATAL_ERROR ("Device does not support eui 48 addresses: cannot be added to bridge.");
248  }
249  if (!bridgePort->SupportsSendFrom ())
250  {
251  NS_FATAL_ERROR ("Device does not support SendFrom: cannot be added to bridge.");
252  }
253  if (m_address == Mac48Address ())
254  {
255  m_address = Mac48Address::ConvertFrom (bridgePort->GetAddress ());
256  }
257 
258  NS_LOG_DEBUG ("RegisterProtocolHandler for " << bridgePort->GetInstanceTypeId ().GetName ());
259  m_node->RegisterProtocolHandler (MakeCallback (&BridgeNetDevice::ReceiveFromDevice, this),
260  0, bridgePort, true);
261  m_ports.push_back (bridgePort);
262  m_channel->AddChannel (bridgePort->GetChannel ());
263 }
264 
265 void
266 BridgeNetDevice::SetIfIndex (const uint32_t index)
267 {
269  m_ifIndex = index;
270 }
271 
272 uint32_t
274 {
276  return m_ifIndex;
277 }
278 
281 {
283  return m_channel;
284 }
285 
286 void
288 {
290  m_address = Mac48Address::ConvertFrom (address);
291 }
292 
293 Address
295 {
297  return m_address;
298 }
299 
300 bool
301 BridgeNetDevice::SetMtu (const uint16_t mtu)
302 {
304  m_mtu = mtu;
305  return true;
306 }
307 
308 uint16_t
310 {
312  return m_mtu;
313 }
314 
315 
316 bool
318 {
320  return true;
321 }
322 
323 
324 void
326 {}
327 
328 
329 bool
331 {
333  return true;
334 }
335 
336 
337 Address
339 {
341  return Mac48Address ("ff:ff:ff:ff:ff:ff");
342 }
343 
344 bool
346 {
348  return true;
349 }
350 
351 Address
353 {
354  NS_LOG_FUNCTION (this << multicastGroup);
355  Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
356  return multicast;
357 }
358 
359 
360 bool
362 {
364  return false;
365 }
366 
367 bool
369 {
371  return true;
372 }
373 
374 
375 bool
376 BridgeNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
377 {
379  return SendFrom (packet, m_address, dest, protocolNumber);
380 }
381 
382 bool
383 BridgeNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
384 {
387 
388  // try to use the learned state if data is unicast
389  if (!dst.IsGroup ())
390  {
391  Ptr<NetDevice> outPort = GetLearnedState (dst);
392  if (outPort != NULL)
393  {
394  outPort->SendFrom (packet, src, dest, protocolNumber);
395  return true;
396  }
397  }
398 
399  // data was not unicast or no state has been learned for that mac
400  // address => flood through all ports.
401  for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
402  iter != m_ports.end (); iter++)
403  {
404  Ptr<NetDevice> port = *iter;
405  port->SendFrom (packet, src, dest, protocolNumber);
406  }
407 
408  return true;
409 }
410 
411 
412 Ptr<Node>
414 {
416  return m_node;
417 }
418 
419 
420 void
422 {
424  m_node = node;
425 }
426 
427 
428 bool
430 {
432  return true;
433 }
434 
435 
436 void
438 {
440  m_rxCallback = cb;
441 }
442 
443 void
445 {
447  m_promiscRxCallback = cb;
448 }
449 
450 bool
452 {
454  return true;
455 }
456 
458 {
459  NS_LOG_FUNCTION (this << addr);
460  return Mac48Address::GetMulticast (addr);
461 }
462 
463 } // namespace ns3
void AddBridgePort(Ptr< NetDevice > bridgePort)
Add a 'port' to a bridge device.
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
static bool IsMatchingType(const Address &address)
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual bool IsBridge(void) const
Return true if the net device is acting as a bridge.
virtual bool IsPointToPoint(void) const
Return true if the net device is on a point-to-point link.
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
virtual void SetIfIndex(const uint32_t index)
virtual uint32_t GetIfIndex(void) const
uint64_t GetUid(void) const
Definition: packet.cc:412
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual bool IsMulticast(void) const
virtual Ptr< Channel > GetChannel(void) const
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
virtual void SetAddress(Address address)
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
virtual void AddLinkChangeCallback(Callback< void > callback)
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
a polymophic address class
Definition: address.h:86
static Mac48Address GetMulticast(Ipv4Address address)
virtual uint16_t GetMtu(void) const
virtual bool SetMtu(const uint16_t mtu)
virtual bool SupportsSendFrom() const
virtual bool IsBroadcast(void) const
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
virtual Address GetBroadcast(void) const
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
static Mac48Address ConvertFrom(const Address &address)
virtual bool NeedsArp(void) const
virtual void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
virtual Address GetAddress(void) const
bool IsGroup(void) const
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Make and return a MAC multicast address using the provided multicast group.
an EUI-48 address
Definition: mac48-address.h:41
static Time Now(void)
Definition: simulator.cc:179
virtual Ptr< Node > GetNode(void) const
virtual void DoDispose(void)
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:218
Describes an IPv6 address.
Definition: ipv6-address.h:44
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
virtual void SetNode(Ptr< Node > node)
virtual bool IsLinkUp(void) const