Basic MAC plugins functionality implemented
authorPavel Boyko <boyko@iitp.ru>
Wed, 18 Mar 2009 17:40:38 +0300
changeset 4844 3c38e23fa821
parent 4843 f65f22ef327e
child 4845 684e65994112
Basic MAC plugins functionality implemented
src/devices/mesh/mesh-wifi-interface-mac-plugin.h
src/devices/mesh/mesh-wifi-interface-mac.cc
src/devices/mesh/mesh-wifi-interface-mac.h
src/devices/mesh/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac-plugin.h	Wed Mar 18 17:40:38 2009 +0300
@@ -0,0 +1,74 @@
+/* -*- 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;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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
+ * 
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIINTERFACEMACPLUGIN_H_
+#define MESHWIFIINTERFACEMACPLUGIN_H_
+
+#include "ns3/wifi-mac-header.h"
+#include "ns3/packet.h"
+#include "ns3/mac48-address.h"
+#include "ns3/mesh-wifi-beacon.h"
+#include "ns3/ref-count-base.h"
+
+namespace ns3 {
+
+class MeshWifiInterfaceMac;
+  
+/**
+ * \ingroup mesh
+ * 
+ * \brief Common interface for mesh point interface MAC plugins
+ * 
+ * TODO: plugins description
+ */
+class MeshWifiInterfaceMacPlugin : public RefCountBase
+{
+public:
+  /// C-tor creates unplugged plugin
+  MeshWifiInterfaceMacPlugin() { /*do nothing*/}
+  /// This is for subclasses
+  virtual ~MeshWifiInterfaceMacPlugin() { /*do nothing*/ }
+  
+  /// Each plugin must be installed on interface to work 
+  virtual void SetParent(MeshWifiInterfaceMac * parent) = 0; 
+  /** 
+   * \brief Process received frame
+   * 
+   * \return false if (and only if) frame should be dropped
+   * TODO define when MAC call this
+   */
+  virtual bool Receive(Ptr<Packet> packet, const WifiMacHeader & header) = 0;
+  /**
+   * \brief Update frame before it will be forwarded down
+   * 
+   * \return false if (and only if) frame should be dropped
+   * TODO define when MAC call this, preconditions & postconditions
+   */
+  virtual bool UpdateOutcomingFrame(Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const = 0;
+  /**
+   * \brief Update beacon before it will be formed and sent
+   *  
+   * TODO define when MAC call this
+   */
+  virtual void UpdateBeacon(MeshWifiBeacon & beacon) const;
+};
+
+} // namespace ns3
+#endif /* MESHWIFIINTERFACEMACPLUGIN_H_ */
--- a/src/devices/mesh/mesh-wifi-interface-mac.cc	Wed Mar 18 16:08:49 2009 +0300
+++ b/src/devices/mesh/mesh-wifi-interface-mac.cc	Wed Mar 18 17:40:38 2009 +0300
@@ -300,6 +300,16 @@
 }
 
 //-----------------------------------------------------------------------------
+// Plugins
+//-----------------------------------------------------------------------------
+void 
+MeshWifiInterfaceMac::InstallPlugin( Ptr<MeshWifiInterfaceMacPlugin> plugin)
+{
+  plugin->SetParent(this);
+  m_plugins.push_back(plugin);
+}
+
+//-----------------------------------------------------------------------------
 // Forward frame up/down
 //-----------------------------------------------------------------------------
 void
@@ -310,51 +320,33 @@
 }
 
 void
-MeshWifiInterfaceMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to)
+MeshWifiInterfaceMac::ForwardDown (Ptr<const Packet> const_packet, Mac48Address from, Mac48Address to)
 {
-  // 1. Create and add mesh header using routing information
-  WifiMacHeader hdr;
-  Ptr<Packet> packet_to_send = packet->Copy();
-  
-  /*
-   TODO:
-  for all plugins {
-    plugin.UpdateOutcomingPacket....(packet, from, to);
-  }
-  */
-  
-  /*
-  WifiMeshHeader meshHdr;
+  // copy packet to allow modifications
+  Ptr<Packet> packet = const_packet->Copy();
   
-  // TODO: Address 1 we receive from HWMP tag
-  HwmpTag tag;
-  NS_ASSERT(packet->FindFirstMatchingTag(tag));
-  meshHdr.SetMeshTtl(tag.GetTtl());
-  meshHdr.SetMeshSeqno(tag.GetSeqno());
-#if 0
-  NS_LOG_DEBUG(
-    "TX Packet sa = "<<from<<
-    ", da = "<<to<<
-    ", ra = "<<tag.GetAddress()<<
-    ", I am "<<GetAddress()<<
-    ", ttl = "<<(int)meshHdr.GetMeshTtl()
-  );
-#endif
-  if (to!= Mac48Address::GetBroadcast())
-    NS_ASSERT(tag.GetAddress()!=Mac48Address::GetBroadcast());
-  
+  WifiMacHeader hdr;
   hdr.SetTypeData ();
-  hdr.SetAddr1 (tag.GetAddress());
   hdr.SetAddr2 (GetAddress ());
   hdr.SetAddr3 (to);
   hdr.SetAddr4 (from);
   hdr.SetDsFrom ();
   hdr.SetDsTo ();
   
-  packet_to_send->AddHeader(meshHdr);
-  */
+  // Address 1 is unknwon here. Routing plugin is responsible to correctly set it.
+  hdr.SetAddr1 (Mac48Address ());
   
-  // 2. Queue frame
+  // 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);
 
   if (destination->IsBrandNew ())
@@ -367,7 +359,7 @@
         }
       destination->RecordDisassociated ();
     }
-  m_BE->Queue (packet_to_send, hdr);
+  m_BE->Queue (packet, hdr);
 }
 
 SupportedRates
@@ -476,7 +468,6 @@
   m_beaconSendEvent = Simulator::Schedule (GetTBTT(), &MeshWifiInterfaceMac::SendBeacon, this);
 }
 
-
 void 
 MeshWifiInterfaceMac::ScheduleNextBeacon()
 {
@@ -496,205 +487,60 @@
   // Form & send beacon
   MeshWifiBeacon beacon(GetSsid (), GetSupportedRates (), m_beaconInterval.GetMicroSeconds ());
   
-  /*
-    TODO ask all plugins to add smth. to beacon
-   for all plugins {
-     plugin.UpdateBeacon(beacon);
-   }
-  */
+  // 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();
 }
 
-
 void
 MeshWifiInterfaceMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr)
 {
-  /* TODO
+  // Process beacon
   if (hdr->IsBeacon ())
     {
-      MgtMeshBeaconHeader beacon;
+      MgtBeaconHeader beacon_hdr;
       Mac48Address from = hdr->GetAddr2();
-      packet->RemoveHeader (beacon);
+      
+      packet->PeekHeader (beacon_hdr);
+      
       NS_LOG_DEBUG("Beacon received from "<<hdr->GetAddr2()<<
                    " to "<<GetAddress()<<
                    " at "<<Simulator::Now ().GetMicroSeconds ()<<
                    " microseconds");
-#if 0
-      NeighboursTimingUnitsList neighbours;
-      neighbours = beacon.GetWifiBeaconTimingElement().GetNeighboursTimingElementsList();
-      for (NeighboursTimingUnitsList::const_iterator j = neighbours.begin(); j!= neighbours.end(); j++)
-        fprintf(
-          stderr,
-          "neigbours:\nAID=%u, last_beacon=%u ,beacon_interval=%u\n",
-          (*j)->GetAID(),
-          (*j)->GetLastBeacon(),
-          (*j)->GetBeaconInterval()
-        );
-#endif
-      m_peerManager->SetReceivedBeaconTimers(
-        GetAddress(),
-        from,
-        Simulator::Now (),
-        MicroSeconds(beacon.GetBeaconIntervalUs()),
-        beacon.GetWifiBeaconTimingElement()
-      );
-      if (!beacon.GetSsid().IsEqual(GetSsid()))
-        return;
-      SupportedRates rates = beacon.GetSupportedRates ();
-      WifiRemoteStation *peerSta = m_stationManager->Lookup (hdr->GetAddr2 ());
-      for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
-        {
-          WifiMode mode = m_phy->GetMode (i);
-          if (rates.IsSupportedRate (mode.GetDataRate ()))
-            {
-              peerSta->AddSupportedMode (mode);
-              if (rates.IsBasicRate (mode.GetDataRate ()))
-                {
-                  m_stationManager->AddBasicMode (mode);
-                }
-            }
-        }
-      // TODO:Chack MeshConfigurationElement(now is nothing
-      // to be checked)
-      m_peerManager->AskIfOpenNeeded(GetAddress(), from);
-      return;
-    }
-  if (hdr->IsMultihopAction())
-    {
-      WifiMeshHeader meshHdr;
-      //no mesh header parameters are needed here:
-      //TODO: check TTL
-      packet->RemoveHeader(meshHdr);
-      WifiMeshMultihopActionHeader multihopHdr;
-      //parse multihop action header:
-      packet->RemoveHeader(multihopHdr);
-      WifiMeshMultihopActionHeader::ACTION_VALUE
-      actionValue = multihopHdr.GetAction();
-      switch (multihopHdr.GetCategory())
-        {
-        case WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT:
+      
+      // update supported rates
+      if (beacon_hdr.GetSsid().IsEqual(GetSsid()))
         {
-          Mac48Address peerAddress;
-          MeshMgtPeerLinkManFrame peer_frame;
-          if (hdr->GetAddr1 () != GetAddress ())
-            return;
-          peerAddress = hdr->GetAddr2();
-          packet->RemoveHeader (peer_frame);
-          if (actionValue.peerLink != WifiMeshMultihopActionHeader::PEER_LINK_CLOSE)
-            {
-              //check Supported Rates
-              SupportedRates rates = peer_frame.GetSupportedRates();
-              for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
-                {
-                  WifiMode mode = m_stationManager->GetBasicMode (i);
-                  if (!rates.IsSupportedRate (mode.GetDataRate ()))
-                    {
-                      m_peerManager->ConfigurationMismatch(GetAddress(), peerAddress);
-                      return;
-                    }
-                }
-              //Check SSID
-              if (!peer_frame.GetMeshId().IsEqual(GetSsid()))
-                {
-                  m_peerManager->ConfigurationMismatch(GetAddress(), peerAddress);
-                  return;
-                }
-            }
-          switch (actionValue.peerLink)
-            {
-            case WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM:
-              m_peerManager->SetConfirmReceived(
-                GetAddress(),
-                peerAddress,
-                peer_frame.GetAid(),
-                peer_frame.GetPeerLinkManagementElement(),
-                m_meshConfig
-              );
-              return;
-            case WifiMeshMultihopActionHeader::PEER_LINK_OPEN:
-              m_peerManager->SetOpenReceived(
-                GetAddress(),
-                peerAddress,
-                peer_frame.GetPeerLinkManagementElement(),
-                m_meshConfig
-              );
-              return;
-            case WifiMeshMultihopActionHeader::PEER_LINK_CLOSE:
-              m_peerManager->SetCloseReceived(
-                GetAddress(),
-                peerAddress,
-                peer_frame.GetPeerLinkManagementElement()
-              );
-              return;
-            default:
-              return;
-            }
-          break;
-        }
-        case WifiMeshMultihopActionHeader::MESH_PATH_SELECTION:
-        {
-          if (!m_peerManager->IsActiveLink(GetAddress(), hdr->GetAddr2()))
-            return;
-          switch (actionValue.pathSelection)
-            {
-            case WifiMeshMultihopActionHeader::PATH_REQUEST:
-            {
-              WifiPreqInformationElement preq;
-              packet->RemoveHeader(preq);
-              //TODO:recalculate
-              //metric
-              m_preqReceived(preq, hdr->GetAddr2(), CalculateMetric(hdr->GetAddr2()));
-              return;
-            }
-            case WifiMeshMultihopActionHeader::PATH_REPLY:
-            {
-              WifiPrepInformationElement prep;
-              packet->RemoveHeader(prep);
-              m_prepReceived(prep, hdr->GetAddr2(), CalculateMetric(hdr->GetAddr2()));
-            }
-            return;
-            case WifiMeshMultihopActionHeader::PATH_ERROR:
-            {
-              WifiPerrInformationElement perr;
-              packet->RemoveHeader(perr);
-              m_perrReceived(perr, hdr->GetAddr2());
-            }
-            return;
-            case WifiMeshMultihopActionHeader::ROOT_ANNOUNCEMENT:
-              return;
-            }
-        }
-        default:
-          break;
+          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);
+            if (rates.IsSupportedRate (mode.GetDataRate ()))
+              {
+                peerSta->AddSupportedMode (mode);
+                if (rates.IsBasicRate (mode.GetDataRate ()))
+                  m_stationManager->AddBasicMode (mode);
+              }
+          }
         }
     }
-  if (hdr->IsData())
+  
+  // Filter frame through all installed plugins
+  for (PluginList::iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
     {
-      NS_ASSERT((hdr->IsFromDs()) && (hdr->IsToDs()));
-      NS_ASSERT(hdr->GetAddr4()!=Mac48Address::GetBroadcast());
-      //check seqno
-      WifiMeshHeader meshHdr;
-      packet->RemoveHeader(meshHdr);
-      NS_LOG_DEBUG(
-        "DATA TA="<< hdr->GetAddr2()<<
-        ", da="<<hdr->GetAddr3()<<
-        ", sa="<<hdr->GetAddr4()<<
-        ", TTL="<<(int)meshHdr.GetMeshTtl());
-      HwmpTag tag;
-      //mesh header is present within DATA and multihop action frames, so it must be done within MAC
-      tag.SetSeqno(meshHdr.GetMeshSeqno());
-      tag.SetAddress(hdr->GetAddr2());
-      tag.SetTtl(meshHdr.GetMeshTtl());
-      //metric should be later
-      packet->RemoveAllTags();
-      packet->AddTag(tag);
-      if (m_peerManager->IsActiveLink(GetAddress(), hdr->GetAddr2()))
-        ForwardUp(packet, hdr->GetAddr4(), hdr->GetAddr3());
+      bool drop = !((*i)->Receive(packet, *hdr));
+      if (drop) return; // plugin drops frame
     }
-    */
+    
+  // Forward data up
+  if (hdr->IsData())
+      ForwardUp(packet, hdr->GetAddr4(), hdr->GetAddr3());
 }
   
 } // namespace ns3
--- a/src/devices/mesh/mesh-wifi-interface-mac.h	Wed Mar 18 16:08:49 2009 +0300
+++ b/src/devices/mesh/mesh-wifi-interface-mac.h	Wed Mar 18 17:40:38 2009 +0300
@@ -35,6 +35,7 @@
 #include "ns3/wifi-remote-station-manager.h"
 #include "ns3/mesh-wifi-peer-manager.h"
 #include "ns3/wifi-mac.h"
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
 
 namespace ns3 {
 
@@ -137,7 +138,8 @@
   
   ///\name Plugins
   //\{
-  // TODO
+  /// Install plugin. TODO return unique ID to allow unregister plugins
+  void InstallPlugin(Ptr<MeshWifiInterfaceMacPlugin> plugin);
   //\}
   
 private:
@@ -212,6 +214,10 @@
   
   /// "Timer" for the next beacon 
   EventId m_beaconSendEvent;
+  
+  typedef std::vector< Ptr<MeshWifiInterfaceMacPlugin> > PluginList; 
+  /// List of all installed plugins
+  PluginList m_plugins;
 };
 
 } // namespace ns3
--- a/src/devices/mesh/wscript	Wed Mar 18 16:08:49 2009 +0300
+++ b/src/devices/mesh/wscript	Wed Mar 18 17:40:38 2009 +0300
@@ -31,6 +31,7 @@
         'mesh-l2-routing-protocol.h',
         'mesh-wifi-beacon.h',
         'mesh-wifi-interface-mac.h',
+        'mesh-wifi-interface-mac-plugin.h',
         # Dirty
         'dot11s-codes.h',
         'hwmp-state.h',