add MacRxMiddle to build
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue, 09 Oct 2007 12:30:51 +0200
changeset 1927 7ef830068f1d
parent 1926 88023edeb6ea
child 1928 828fd4aa87f9
add MacRxMiddle to build
src/devices/wifi/mac-rx-middle.cc
src/devices/wifi/mac-rx-middle.h
src/devices/wifi/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mac-rx-middle.cc	Tue Oct 09 12:30:51 2007 +0200
@@ -0,0 +1,303 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "mac-rx-middle.h"
+#include "ns3/packet.h"
+#include "wifi-mac-header.h"
+
+#include <cassert>
+#include <list>
+
+#define noRX_MIDDLE_TRACE 1
+
+#ifdef RX_MIDDLE_TRACE
+#include <iostream>
+# define TRACE(x) \
+  std::cout <<"RX MIDDLE "<<x<<std::endl;
+#else /* RX_MIDDLE_TRACE */
+# define TRACE(x)
+#endif /* RX_MIDDLE_TRACE */
+
+namespace ns3 {
+
+
+class OriginatorRxStatus {
+private:
+  typedef std::list<Packet> Fragments;
+  typedef std::list<Packet>::const_iterator FragmentsCI;
+
+  bool m_defragmenting;
+  uint16_t m_lastSequenceControl;
+  Fragments m_fragments;
+public:
+  OriginatorRxStatus () {
+    /* this is a magic value necessary. */
+    m_lastSequenceControl = 0xffff;
+    m_defragmenting = false;
+  }
+  ~OriginatorRxStatus () {
+    for (FragmentsCI i = m_fragments.begin (); i != m_fragments.end (); i++) 
+      {
+        // XXX ?
+      }
+    m_fragments.erase (m_fragments.begin (), m_fragments.end ());
+  }
+  bool IsDeFragmenting (void) {
+    return m_defragmenting;
+  }
+  void AccumulateFirstFragment (Packet const packet) {
+    assert (!m_defragmenting);
+    m_defragmenting = true;
+    m_fragments.push_back (packet);
+  }
+  Packet AccumulateLastFragment (Packet const packet) {
+    assert (m_defragmenting);
+    m_fragments.push_back (packet);
+    m_defragmenting = false;
+    Packet full;
+    for (FragmentsCI i = m_fragments.begin (); i != m_fragments.end (); i++) 
+      {
+        full.AddAtEnd (*i);
+      }
+    m_fragments.erase (m_fragments.begin (), m_fragments.end ());
+    return full;
+  }
+  void AccumulateFragment (Packet const packet) {
+    assert (m_defragmenting);
+    m_fragments.push_back (packet);
+  }
+  bool IsNextFragment (uint16_t sequenceControl) {
+    if ((sequenceControl >> 4) == (m_lastSequenceControl >> 4) &&
+        (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f)+1)) 
+      {
+        return true;
+      } 
+    else 
+      {
+        return false;
+      }
+  }
+  uint16_t GetLastSequenceControl (void) 
+  {
+    return m_lastSequenceControl;
+  }
+  void SetSequenceControl (uint16_t sequenceControl) 
+  {
+    m_lastSequenceControl = sequenceControl;
+  }
+  
+};
+
+
+MacRxMiddle::MacRxMiddle ()
+{}
+
+MacRxMiddle::~MacRxMiddle ()
+{
+  for (OriginatorsI i = m_originatorStatus.begin ();
+       i != m_originatorStatus.end (); i++) 
+    {
+      delete (*i).second;
+    }
+  m_originatorStatus.erase (m_originatorStatus.begin (),
+                            m_originatorStatus.end ());
+  for (QosOriginatorsI i = m_qosOriginatorStatus.begin ();
+       i != m_qosOriginatorStatus.end (); i++) 
+    {
+      delete (*i).second;
+    }
+  m_qosOriginatorStatus.erase (m_qosOriginatorStatus.begin (),
+                               m_qosOriginatorStatus.end ());
+}
+
+void 
+MacRxMiddle::SetForwardCallback (ForwardUpCallback callback)
+{
+  m_callback = callback;
+}
+
+bool
+MacRxMiddle::SequenceControlSmaller (int seqca, int seqcb)
+{
+  int seqa = seqca >> 4;
+  int seqb = seqcb >> 4;
+  int delta = seqb - seqa;
+  TRACE ("seqb="<<seqb<<", seqa="<<seqa<<", delta="<<delta);
+  if (delta <= 0 && delta < -2048) 
+    {
+      return true;
+    } 
+  else if (delta >= 0 && delta < 2048) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+
+
+OriginatorRxStatus *
+MacRxMiddle::Lookup (WifiMacHeader const *hdr)
+{
+  OriginatorRxStatus *originator;
+  Mac48Address source = hdr->GetAddr2 ();
+  if (hdr->IsQosData () &&
+      !hdr->GetAddr2 ().IsBroadcast ()) 
+    {
+      /* only for qos data non-broadcast frames */
+      originator = m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid ())];
+      if (originator == 0) 
+        {
+          originator = new OriginatorRxStatus ();
+          m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid ())] = originator;
+        }
+    } 
+  else 
+    {
+      /* - management frames
+       * - qos data broadcast frames
+       * - nqos data frames
+       * see section 7.1.3.4.1
+       */
+      originator = m_originatorStatus[source];
+      if (originator == 0) 
+        {
+          originator = new OriginatorRxStatus ();
+          m_originatorStatus[source] = originator;
+        }
+    }
+  return originator;
+}
+
+bool
+MacRxMiddle::IsDuplicate (WifiMacHeader const*hdr, 
+         OriginatorRxStatus *originator) const
+{
+  if (originator->GetLastSequenceControl () == hdr->GetSequenceControl ()) 
+    {
+      return true;
+    }
+  return false;
+}
+
+Packet 
+MacRxMiddle::HandleFragments (Packet packet, WifiMacHeader const*hdr,
+             OriginatorRxStatus *originator, bool *complete)
+{
+  if (originator->IsDeFragmenting ()) 
+    {
+      if (hdr->IsMoreFragments ()) 
+        {
+          if (originator->IsNextFragment (hdr->GetSequenceControl ())) 
+            {
+              TRACE ("accumulate fragment seq="<<hdr->GetSequenceNumber ()<<
+                     ", frag="<<hdr->GetFragmentNumber ()<<
+                     ", size="<<packet.GetSize ());
+              originator->AccumulateFragment (packet);
+              originator->SetSequenceControl (hdr->GetSequenceControl ());
+            } 
+          else 
+            {
+              TRACE ("non-ordered fragment");
+            }
+          *complete = false;
+          return Packet ();
+        } 
+      else 
+        {
+          if (originator->IsNextFragment (hdr->GetSequenceControl ())) 
+            {
+              TRACE ("accumulate last fragment seq="<<hdr->GetSequenceNumber ()<<
+                     ", frag="<<hdr->GetFragmentNumber ()<<
+                     ", size="<<hdr->GetSize ());
+              packet = originator->AccumulateLastFragment (packet);
+              originator->SetSequenceControl (hdr->GetSequenceControl ());
+              *complete = true;
+              return packet;
+            } 
+          else 
+            {
+              TRACE ("non-ordered fragment");
+              *complete = false;
+              return Packet ();
+            }
+        }
+    } 
+  else 
+    {
+      if (hdr->IsMoreFragments ()) 
+        {
+          TRACE ("accumulate first fragment seq="<<hdr->GetSequenceNumber ()<<
+                 ", frag="<<hdr->GetFragmentNumber ()<<
+                 ", size="<<packet.GetSize ());
+          originator->AccumulateFirstFragment (packet);
+          originator->SetSequenceControl (hdr->GetSequenceControl ());
+          *complete = false;
+          return Packet ();
+        } 
+      else 
+        {
+          *complete = true;
+          return packet;
+        }
+    }
+}
+
+void
+MacRxMiddle::Receive (Packet packet, WifiMacHeader const *hdr)
+{
+  OriginatorRxStatus *originator = Lookup (hdr);
+  if (hdr->IsData ()) 
+    {
+      assert (SequenceControlSmaller (originator->GetLastSequenceControl (), 
+                                      hdr->GetSequenceControl ()));
+      // filter duplicates.
+      if (IsDuplicate (hdr, originator)) 
+        {
+          TRACE ("duplicate from="<<hdr->GetAddr2 ()<<
+                 ", seq="<<hdr->GetSequenceNumber ()<<
+                 ", frag="<<hdr->GetFragmentNumber ());
+          return;
+        }
+      bool complete;
+      Packet agregate = HandleFragments (packet, hdr, originator, &complete);
+      if (!complete) 
+        {
+          return;
+        }
+      TRACE ("forwarding data from="<<hdr->GetAddr2 ()<<
+             ", seq="<<hdr->GetSequenceNumber ()<<
+             ", frag="<<hdr->GetFragmentNumber ());
+      originator->SetSequenceControl (hdr->GetSequenceControl ());
+      m_callback (agregate, hdr);
+    } 
+  else 
+    {
+      TRACE ("forwarding "<<hdr->GetTypeString ()<<
+             ", seq="<<hdr->GetSequenceNumber ()<<
+             ", frag="<<hdr->GetFragmentNumber ());
+      originator->SetSequenceControl (hdr->GetSequenceControl ());
+      m_callback (packet, hdr);
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mac-rx-middle.h	Tue Oct 09 12:30:51 2007 +0200
@@ -0,0 +1,66 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef MAC_RX_MIDDLE_H
+#define MAC_RX_MIDDLE_H
+
+#include <map>
+#include <utility>
+#include "ns3/callback.h"
+#include "ns3/mac48-address.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+
+class WifiMacHeader;
+class OriginatorRxStatus;
+
+class MacRxMiddle
+{
+public:
+  typedef Callback<void, Packet , WifiMacHeader const *> ForwardUpCallback;
+
+  MacRxMiddle ();
+  ~MacRxMiddle ();
+
+  void SetForwardCallback (ForwardUpCallback callback);
+
+  void Receive (Packet packet, WifiMacHeader const *hdr);
+private:
+  OriginatorRxStatus *Lookup (WifiMacHeader const*hdr);
+  bool IsDuplicate (WifiMacHeader const *hdr, OriginatorRxStatus *originator) const;
+  Packet HandleFragments (Packet packet, WifiMacHeader const*hdr,
+                          OriginatorRxStatus *originator, bool *complete);
+  bool SequenceControlSmaller (int seqa, int seqb);
+
+  typedef std::map <Mac48Address, OriginatorRxStatus *, std::less<Mac48Address> > Originators;
+  typedef std::map <std::pair<Mac48Address, uint8_t>, OriginatorRxStatus *, std::less<std::pair<Mac48Address,uint8_t> > > QosOriginators;
+  typedef std::map <Mac48Address, OriginatorRxStatus *, std::less<Mac48Address> >::iterator OriginatorsI;
+  typedef std::map <std::pair<Mac48Address, uint8_t>, OriginatorRxStatus *, std::less<std::pair<Mac48Address,uint8_t> > >::iterator QosOriginatorsI;
+  Originators m_originatorStatus;
+  QosOriginators m_qosOriginatorStatus;
+  ForwardUpCallback m_callback;
+};
+
+} // namespace ns3
+
+
+#endif /* MAC_RX_MIDDLE_H */
--- a/src/devices/wifi/wscript	Tue Oct 09 12:30:37 2007 +0200
+++ b/src/devices/wifi/wscript	Tue Oct 09 12:30:51 2007 +0200
@@ -20,6 +20,7 @@
         'dcf.cc',
         'wifi-mac-queue.cc',
         'mac-tx-middle.cc',
+        'mac-rx-middle.cc',
         ]
     headers = bld.create_obj('ns3header')
     headers.source = [