src/devices/mesh/mesh-wifi-interface-mac.cc
changeset 4934 345b49df838b
parent 4929 1689c94d7442
child 4944 779b641cff5a
--- a/src/devices/mesh/mesh-wifi-interface-mac.cc	Thu Apr 02 13:38:38 2009 +0400
+++ b/src/devices/mesh/mesh-wifi-interface-mac.cc	Thu Apr 02 14:33:38 2009 +0400
@@ -1,7 +1,7 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/* 
+/*
  * Copyright (c) 2009 IITP RAS
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation;
@@ -14,7 +14,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
+ *
  * Authors: Kirill Andreev <andreev@iitp.ru>
  *          Pavel Boyko <boyko@iitp.ru>
  */
@@ -30,6 +30,7 @@
 #include "ns3/mesh-wifi-mac-header.h"
 #include "ns3/random-variable.h"
 #include "ns3/simulator.h"
+#include "ns3/yans-wifi-phy.h"
 
 NS_LOG_COMPONENT_DEFINE ("MeshWifiInterfaceMac");
 
@@ -67,7 +68,7 @@
 MeshWifiInterfaceMac::MeshWifiInterfaceMac ()
 {
   NS_LOG_FUNCTION (this);
-  
+
   m_rxMiddle = new MacRxMiddle ();
   m_rxMiddle->SetForwardCallback (MakeCallback (&MeshWifiInterfaceMac::Receive, this));
 
@@ -187,6 +188,8 @@
   m_phy = phy;
   m_dcfManager->SetupPhyListener (phy);
   m_low->SetPhy (phy);
+
+  NS_LOG_DEBUG("SetWifiPhy: Can switch channel now: " << CanSwitchChannel() ); // TMP
 }
 
 void
@@ -290,21 +293,75 @@
   m_VO = 0;
   m_beaconSendEvent.Cancel ();
   m_beaconDca = 0;
-  
+
   WifiMac::DoDispose ();
 }
 
 //-----------------------------------------------------------------------------
 // Plugins
 //-----------------------------------------------------------------------------
-void 
+void
 MeshWifiInterfaceMac::InstallPlugin ( Ptr<MeshWifiInterfaceMacPlugin> plugin)
 {
+  NS_LOG_FUNCTION (this);
+
   plugin->SetParent (this);
   m_plugins.push_back (plugin);
 }
 
 //-----------------------------------------------------------------------------
+// Switch channels
+//-----------------------------------------------------------------------------
+bool MeshWifiInterfaceMac::CanSwitchChannel () const
+{
+  NS_LOG_FUNCTION (this);
+
+  // now only YansWifiPhy can switch channels runtime
+  if (m_phy != 0)
+    {
+      Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+      return (phy != 0);
+    }
+  else
+    return false;
+}
+
+uint16_t MeshWifiInterfaceMac::GetFrequencyChannel () const
+{
+  NS_LOG_FUNCTION (this);
+  NS_ASSERT (m_phy != 0); // need PHY to set/get channel
+
+  Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+  if (phy != 0)
+    return phy->GetFrequencyChannel ();
+  else
+    return 0;
+}
+
+void MeshWifiInterfaceMac::SwitchFrequencyChannel (uint16_t new_id)
+{
+  NS_LOG_FUNCTION (this);
+  NS_ASSERT (m_phy != 0); // need PHY to set/get channel
+  /* TODO
+   *
+   * Correct channel switching is:
+   *
+   * 1. Interface down, e.g. to stop packets from layer 3
+   * 2. Wait before all output queues will be empty
+   * 3. Switch PHY channel
+   * 4. Interface up
+   *
+   * Now we use dirty channel switch -- just change frequency
+   */
+  NS_ASSERT(CanSwitchChannel());
+
+  Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+  phy->SetFrequencyChannel (new_id);
+  // Don't know NAV on new channel
+  m_dcfManager->NotifyNavResetNow (Seconds (0));
+}
+
+//-----------------------------------------------------------------------------
 // Forward frame up/down
 //-----------------------------------------------------------------------------
 void
@@ -319,7 +376,7 @@
 {
   // copy packet to allow modifications
   Ptr<Packet> packet = const_packet->Copy ();
-  
+
   WifiMacHeader hdr;
   hdr.SetTypeData ();
   hdr.SetAddr2 (GetAddress ());
@@ -327,19 +384,20 @@
   hdr.SetAddr4 (from);
   hdr.SetDsFrom ();
   hdr.SetDsTo ();
+
   // Address 1 is unknwon here. Routing plugin is responsible to correctly set it.
   hdr.SetAddr1 (Mac48Address ());
-  
+
   // Filter packet through all installed plugins
   for (PluginList::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
     {
       bool drop = ! ((*i)->UpdateOutcomingFrame(packet, hdr, from, to));
       if (drop) return; // plugin drops frame
     }
-  
+
   // Assert that address1 is set. Assert will fail e.g. if there is no installed routing plugin.
   NS_ASSERT (hdr.GetAddr1() != Mac48Address() );
-  
+
   // Queue frame
   WifiRemoteStation *destination = m_stationManager->Lookup (to);
 
@@ -415,7 +473,7 @@
   m_beaconInterval = interval;
 }
 
-Time 
+Time
 MeshWifiInterfaceMac::GetBeaconInterval () const
 {
   return m_beaconInterval;
@@ -430,7 +488,7 @@
       // Now start sending beacons after some random delay (to avoid collisions)
       UniformVariable coefficient (0.0, m_randomStart.GetSeconds());
       Time randomStart = Seconds (coefficient.GetValue());
-      
+
       m_beaconSendEvent = Simulator::Schedule (randomStart, &MeshWifiInterfaceMac::SendBeacon, this);
       m_tbtt = Simulator::Now() + randomStart;
     }
@@ -455,14 +513,14 @@
 {
   // User of ShiftTbtt () must take care don't shift it to the past
   NS_ASSERT (GetTbtt() + shift > Simulator::Now());
-  
+
   m_tbtt += shift;
   // Shift scheduled event
   Simulator::Cancel (m_beaconSendEvent);
   m_beaconSendEvent = Simulator::Schedule (GetTbtt () - Simulator::Now(), &MeshWifiInterfaceMac::SendBeacon, this);
 }
 
-void 
+void
 MeshWifiInterfaceMac::ScheduleNextBeacon ()
 {
   m_tbtt += GetBeaconInterval ();
@@ -474,19 +532,19 @@
 {
   NS_LOG_FUNCTION (this);
   NS_LOG_DEBUG (GetAddress() <<" is sending beacon");
-  
+
   NS_ASSERT (! m_beaconSendEvent.IsRunning());
   NS_ASSERT (Simulator::Now().GetMicroSeconds() == GetTbtt().GetMicroSeconds());     // assert that beacon is just on time
-   
+
   // Form & send beacon
   MeshWifiBeacon beacon (GetSsid (), GetSupportedRates (), m_beaconInterval.GetMicroSeconds ());
-  
+
   // Ask all plugins to add their specific information elements to beacon
   for (PluginList::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
     (*i)->UpdateBeacon (beacon);
-  
+
   m_beaconDca->Queue (beacon.CreatePacket(), beacon.CreateHeader(GetAddress()));
-  
+
   ScheduleNextBeacon ();
 }
 
@@ -500,20 +558,20 @@
     {
       MgtBeaconHeader beacon_hdr;
       Mac48Address from = hdr->GetAddr2 ();
-      
+
       packet->PeekHeader (beacon_hdr);
-      
+
       NS_LOG_DEBUG ("Beacon received from "<<hdr->GetAddr2()<<
                    " I am "<<GetAddress ()<<
                    " at "<<Simulator::Now ().GetMicroSeconds ()<<
                    " microseconds");
-      
+
       // update supported rates
       if (beacon_hdr.GetSsid ().IsEqual(GetSsid()))
         {
           SupportedRates rates = beacon_hdr.GetSupportedRates ();
           WifiRemoteStation * peerSta = m_stationManager->Lookup (hdr->GetAddr2 ());
-      
+
           for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
           {
             WifiMode mode = m_phy->GetMode (i);
@@ -526,14 +584,14 @@
           }
         }
     }
-  
+
   // Filter frame through all installed plugins
   for (PluginList::iterator i = m_plugins.begin (); i != m_plugins.end(); ++i)
     {
       bool drop = ! ((*i)->Receive(packet, *hdr));
       if (drop) return; // plugin drops frame
     }
-    
+
   // Forward data up
   if (hdr->IsData ())
       ForwardUp (packet, hdr->GetAddr4(), hdr->GetAddr3());