Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(263)

Unified Diff: ns-3.13/src/hidden-markov-error-model/model/hidden-markov-error-model.cc

Issue 6201059: New IEEE 802.11 indoor wireless channel models for ns-3
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ns-3.13/src/hidden-markov-error-model/model/hidden-markov-error-model.cc
diff --git a/ns-3.13/src/hidden-markov-error-model/model/hidden-markov-error-model.cc b/ns-3.13/src/hidden-markov-error-model/model/hidden-markov-error-model.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f5483d329c811a916cac7d9774f071d80f147921
--- /dev/null
+++ b/ns-3.13/src/hidden-markov-error-model/model/hidden-markov-error-model.cc
@@ -0,0 +1,565 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Universidad de Cantabria
+ *
+ * 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: David Gómez Fernández <dgomez@tlmat.unican.es>
+ * Ramón Agüero Calvo <ramon@tlmat.unican.es>
+ */
+
+#include <math.h>
+#include <fstream>
+
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/boolean.h"
+#include "ns3/enum.h"
+#include "ns3/double.h"
+#include "ns3/integer.h"
+#include "ns3/string.h"
+
+#include "ns3/hidden-markov-error-model.h"
+
+using namespace std;
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("HiddenMarkovErrorModel");
+NS_OBJECT_ENSURE_REGISTERED (HiddenMarkovErrorModel);
+
+const bool g_debug = false; //Temporal solution (only for debugging)
+
+TypeId
+HiddenMarkovErrorModel::GetTypeId(void) {
+ static TypeId tid = TypeId ("ns3::HiddenMarkovErrorModel")
+ .SetParent<ErrorModel> ()
+ .AddConstructor<HiddenMarkovErrorModel> ()
+ .AddAttribute ("RanVar",
+ "Random variable which determine a packet to be successfully received or not",
+ RandomVariableValue (UniformVariable (0.0, 1.0)),
+ MakeRandomVariableAccessor (&HiddenMarkovErrorModel::m_ranvar),
+ MakeRandomVariableChecker ())
+ .AddAttribute ("AverageFrameDuration",
+ "Average time (in microseconds) between two consecutive frames (used to model the exponential interarrival process)",
+ DoubleValue (2000.0),
+ MakeDoubleAccessor (&HiddenMarkovErrorModel::m_averageInterFrameDuration),
+ MakeDoubleChecker<double> ())
+ .AddAttribute("InitialState",
+ "Initial simulation state (Default 0)",
+ IntegerValue(0),
+ MakeIntegerAccessor(&HiddenMarkovErrorModel::m_currentState),
+ MakeIntegerChecker<int>())
+ .AddAttribute ("HiddenStates",
+ "Number of hidden states at the Markov's chain",
+ IntegerValue (2),
+ MakeIntegerAccessor (&HiddenMarkovErrorModel::m_hiddenStates),
+ MakeIntegerChecker<int> ())
+ .AddAttribute ("ErrorUnit",
+ "Type of simulation (frames or time)",
+ EnumValue (EU_TIME),
+ MakeEnumAccessor (&HiddenMarkovErrorModel::m_unit),
+ MakeEnumChecker (EU_BYTE, "EU_BYTE",
+ EU_PKT, "EU_PKT",
+ EU_BIT, "EU_BIT",
+ EU_TIME, "EU_TIME"))
+ .AddAttribute("TransitionMatrixFileName",
+ "Name of the file which contains the transition matrix (proprietary format)",
+ StringValue("HMM_16states/HMM_09_TR_1.txt"),
+ MakeStringAccessor(&HiddenMarkovErrorModel::m_transitionMatrixFileName),
+ MakeStringChecker())
+ .AddAttribute("EmissionMatrixFileName",
+ "Name of the file which contains the emission matrix (proprietary format)",
+ StringValue("HMM_16states/HMM_09_EMIS_1.txt"),
+ MakeStringAccessor(&HiddenMarkovErrorModel::m_emissionMatrixFileName),
+ MakeStringChecker())
+ .AddTraceSource ("HiddenMarkovErrorModelRxTrace",
+ "Packet tracing",
+ MakeTraceSourceAccessor (&HiddenMarkovErrorModel::m_rxTrace))
+ ;
+ return tid;
+}
+
+HiddenMarkovErrorModel::HiddenMarkovErrorModel() : m_currentState (0),
+ m_started(false)
+{
+ NS_LOG_FUNCTION_NOARGS();
+// m_hiddenStates = 2;
+// m_unit = EU_TIME;
+// m_averageInterFrameDuration = 2000; //Inter-frame average duration (microseconds)
+// m_ranvar = UniformVariable(0.0, 1.0);
+//
+// m_transitionMatrixFileName = "HMM_16states/HMM_09_TR_1.txt";
+// m_emissionMatrixFileName = "HMM_16states/HMM_09_EMIS_1.txt";
+ //Read coefficients files and load the corresponding parameters
+// GetCoefficients();
+}
+
+HiddenMarkovErrorModel::~HiddenMarkovErrorModel()
+{
+ NS_LOG_FUNCTION_NOARGS();
+ if (m_transitionMatrix.size() > 0)
+ m_transitionMatrix.clear();
+ if (m_emissionMatrix.size() > 0)
+ m_emissionMatrix.clear();
+ if (m_meanDurationVector.size() > 0)
+ m_meanDurationVector.clear();
+}
+
+
+void HiddenMarkovErrorModel::SetTransitionMatrixFileName (string transitionMatrixFileName)
+{
+ NS_LOG_FUNCTION_NOARGS();
+ m_transitionMatrixFileName = transitionMatrixFileName;
+}
+
+string HiddenMarkovErrorModel::GetTransitionMatrixFileName (void) const
+{
+ NS_LOG_FUNCTION_NOARGS();
+ return m_transitionMatrixFileName;
+}
+
+void HiddenMarkovErrorModel::SetEmissionMatrixFileName (string emissionMatrixFileName)
+{
+ NS_LOG_FUNCTION_NOARGS();
+ m_emissionMatrixFileName = emissionMatrixFileName;
+}
+
+string HiddenMarkovErrorModel::GetEmissionMatrixFileName (void) const
+{
+ NS_LOG_FUNCTION_NOARGS();
+ return m_emissionMatrixFileName;
+}
+
+u_int8_t HiddenMarkovErrorModel::GetHiddenStates() const
+{
+ NS_LOG_FUNCTION_NOARGS();
+ return m_hiddenStates;
+}
+
+void HiddenMarkovErrorModel::SetHiddenStates(u_int8_t hiddenStates)
+{
+ NS_LOG_FUNCTION_NOARGS();
+ this->m_hiddenStates = hiddenStates;
+}
+
+double HiddenMarkovErrorModel::GetAverageFrameDuration() const
+{
+ NS_LOG_FUNCTION_NOARGS();
+ return m_averageInterFrameDuration;
+}
+
+void HiddenMarkovErrorModel::SetAverageFrameDuration(double averageFrameDuration)
+{
+ NS_LOG_FUNCTION_NOARGS();
+ this->m_averageInterFrameDuration = averageFrameDuration;
+}
+
+ErrorUnit HiddenMarkovErrorModel::GetUnit() const
+{
+ return m_unit;
+}
+
+void HiddenMarkovErrorModel::SetUnit(ErrorUnit unit)
+{
+ this->m_unit = unit;
+}
+
+int HiddenMarkovErrorModel::GetCurrentState() const
+{
+ return m_currentState;
+}
+
+void HiddenMarkovErrorModel::SetCurrentState(int state)
+{
+ this->m_currentState = state;
+}
+
+
+void HiddenMarkovErrorModel::Enable()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_enable = true;
+}
+
+void HiddenMarkovErrorModel::Disable()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_enable = false;
+}
+
+bool HiddenMarkovErrorModel::IsEnabled() const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_enable;
+}
+
+std::string HiddenMarkovErrorModel::GetCwd() {
+ NS_LOG_FUNCTION_NOARGS();
+ char buf[FILENAME_MAX];
+ char* succ = getcwd(buf, FILENAME_MAX);
+ if (succ)
+ return std::string(succ);
+ return ""; // raise a flag, throw an exception, ...
+}
+
+bool HiddenMarkovErrorModel::GetCoefficients ()
+{
+ NS_LOG_FUNCTION(m_transitionMatrixFileName << m_emissionMatrixFileName);
+
+ string transitionMatrixPath;
+ string emissionMatrixPath;
+
+ fstream transitionMatrixFile;
+ fstream emissionMatrixFile;
+ char line[256];
+
+ int rowNumber,i,j; //Auxiliar counters
+ double coefficient;
+ vector<double> CoefficientsVector;
+
+ //If invoked in a second time), flush the previous maps content
+ if (m_transitionMatrix.size())
+ m_transitionMatrix.clear();
+ if (m_emissionMatrix.size())
+ m_emissionMatrix.clear();
+ if (m_meanDurationVector.size())
+ m_meanDurationVector.clear();
+
+ coefSetIter_t iter_;
+
+ transitionMatrixPath = GetCwd() + "/src/hidden-markov-error-model/configs/" + m_transitionMatrixFileName;
+ emissionMatrixPath = GetCwd() + "/src/hidden-markov-error-model/configs/" + m_emissionMatrixFileName;
+
+ transitionMatrixFile.open((const char *) transitionMatrixPath.c_str(), ios::in);
+ emissionMatrixFile.open((const char *) emissionMatrixPath.c_str(), ios::in);
+
+ rowNumber = 0;
+
+ if (transitionMatrixFile) {
+ while (transitionMatrixFile.getline(line, 256)) {
+ if (rowNumber == 0) { //First item in file--> Number of states in the Hidden Markov Chain
+ m_states = atoi(line);
+ } else { //Rest of values are the coefficient of the channel model
+ j = 0;
+ for (i = 0; i < m_states; i++) {
+ //First value at position '0'
+ if (i == 0) {
+ coefficient = atof(line);
+ CoefficientsVector.push_back(coefficient);
+ j++;
+ } else {
+ while (line[j] != ' ' && line[j] != '\t') { //Look for "white" spaces between Coefficients
+ j++;
+ }
+ coefficient = atof(line + j);
+ j++;
+ CoefficientsVector.push_back(coefficient);
+ }
+ }
+ m_transitionMatrix.insert(pair<int, vector <double> > (rowNumber - 1, CoefficientsVector)); //rowNumber shifted 1 position
+ CoefficientsVector.clear();
+
+ //As seen in the analytical studio, the probability to hold on the same state is calculated as follows:
+ //N_i = 1 / (1 - a_ii)
+
+ m_meanDurationVector.push_back (1 / (1 - (m_transitionMatrix[rowNumber - 1][rowNumber -1 ])));
+ }
+ rowNumber++;
+ }
+ }
+
+ else {
+ NS_LOG_ERROR("File (HMM)" << transitionMatrixPath << " not found: Please fix");
+ return false;
+ }
+
+ //Reset the rowNumber counter
+ rowNumber = 0;
+
+ if (emissionMatrixFile) {
+ while (emissionMatrixFile.getline(line, 256)) {
+ j = 0;
+ for (i = 0; i < m_hiddenStates; i++) {
+ //First value at position '0'
+ if (i == 0) {
+ coefficient = atof(line);
+ CoefficientsVector.push_back(coefficient);
+ j++;
+ } else {
+ while (line[j] != ' ' && line[j] != '\t') { //Look for "white" spaces between Coefficients
+ j++;
+ }
+ coefficient = atof(line + j);
+ j++;
+ CoefficientsVector.push_back(coefficient);
+ }
+ }
+ m_emissionMatrix.insert(pair<int, vector <double> > ((int) rowNumber, CoefficientsVector));
+ CoefficientsVector.clear();
+ rowNumber ++;
+
+ }
+ } else {
+ NS_LOG_ERROR("File (HMM)" << emissionMatrixPath << " not found: Please fix");
+ return false;
+ }
+
+ //DEBUGGING
+#ifdef NS3_LOG_ENABLE
+ if(g_debug)
+ {
+
+ //Print the m_transitionMatrix map
+ printf("---Transition Matrix---\n");
+ for (iter_ = m_transitionMatrix.begin(); iter_ != m_transitionMatrix.end(); iter_ ++ )
+ {
+ for (i = 0; i < (int) (iter_->second).size(); i++)
+ {
+ printf("%f ", (iter_->second)[i]);
+ }
+ printf("\n");
+ }
+
+ //Print the m_emissionMatrix map
+ printf("---Emission Matrix---\n");
+ for (iter_ = m_emissionMatrix.begin(); iter_ != m_emissionMatrix.end();
+ iter_++) {
+ for (i = 0; i < (int) (iter_->second).size(); i++) {
+ printf("%f ", (iter_->second)[i]);
+ }
+ printf("\n");
+ }
+
+
+ //Print the m_meanDurationVector
+ printf("---Mean Duration within each state (in frames)---\n");
+ for (j = 0; j < (int) m_meanDurationVector.size(); j++ )
+ {
+ printf("%f\n", m_meanDurationVector[j]);
+ }
+ }
+
+#endif //NS3_LOG_ENABLE
+
+ transitionMatrixFile.close();
+ emissionMatrixFile.close();
+
+ return true;
+}
+
+bool HiddenMarkovErrorModel::DoCorrupt(Ptr<Packet> packet)
+{
+ NS_LOG_FUNCTION(this);
+ bool corruptedPacket;
+ WifiMacHeader hdr;
+ LlcSnapHeader llcHdr;
+ Ipv4Header ipv4Hdr;
+ UdpHeader udpHdr;
+ TcpHeader tcpHdr;
+
+ Ptr<Packet> pktCopy = packet->Copy();
+
+ pktCopy->RemoveHeader(hdr);
+
+ //In a time-based simulation, start the timers with the first reception
+ if (m_started == false && m_unit == EU_TIME)
+ {
+ m_started = true;
+ InitializeTimer();
+ NS_LOG_DEBUG("Timer initialized");
+ }
+
+ //Decide whether the frame is correct or not according to the frame type (data, TCP or broadcast/control)
+ //Force packet with length < 128 to be always correct
+ if (hdr.IsData() && !hdr.GetAddr1().IsBroadcast())
+ {
+ //We have split the packet decision into the following three conditions:
+ // - ARP frames --> Always correct
+ // - TCP ACK --> Always correct
+ // - Data frames --> Legacy HMM decision process
+ pktCopy->RemoveHeader(llcHdr);
+
+ switch (llcHdr.GetType())
+ {
+ case 0x0806: //ARP
+ corruptedPacket = false;
+ break;
+ case 0x0800: //IP packet
+ pktCopy->RemoveHeader(ipv4Hdr);
+ switch (ipv4Hdr.GetProtocol())
+ {
+ case 6: //TCP
+ pktCopy->RemoveHeader(tcpHdr);
+
+ //Data segments --> To be errored
+ if (pktCopy->GetSize() > 4)
+ corruptedPacket = Decide ();
+ else
+ corruptedPacket = false;
+ break;
+ case 17: //UDP
+ corruptedPacket = Decide();
+ break;
+ default:
+ NS_LOG_ERROR ("Protocol not implemented yet (IP) --> " << ipv4Hdr.GetProtocol());
+ break;
+ }
+ break;
+ default:
+ NS_LOG_ERROR ("Protocol not implemented yet (LLC) --> " << llcHdr.GetType());
+ break;
+ }
+ }
+
+ //Force 802.11 ACKs, broadcast and control/management frames to be correct
+ else if (hdr.IsAck())
+ {
+ corruptedPacket = false;
+
+ }
+ else if (hdr.IsCtl() || hdr.IsMgt() || (hdr.GetAddr1()).IsBroadcast())
+ {
+ corruptedPacket = false;
+ }
+ else
+ {
+ corruptedPacket = false;
+ }
+
+ //Packet-based simulation--> Change state attempt
+ if (m_unit != EU_TIME)
+ ChangeState();
+
+ //Tracing and callbacks
+ m_rxTrace (packet, Simulator::Now(),corruptedPacket, m_currentState);
+ if (!m_rxCallback.IsNull())
+ m_rxCallback (packet, Simulator::Now(),corruptedPacket, m_currentState);
+
+ return corruptedPacket;
+}
+
+bool HiddenMarkovErrorModel::Decide ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ bool corruptedPacket;
+ //Two posibilities:
+ //Time --> Check into the emission matrix (current state)
+ //Frames --> The same criteria as the time-based one and a possible state change
+ if (m_ranvar.GetValue() < (m_emissionMatrix[m_currentState])[0]) //First column in emission matrix --> Error probability (state i)
+ {
+ NS_LOG_LOGIC("CORRUPT! (" << this << ") (" << Simulator::Now().GetSeconds() << ") State: " << m_currentState);
+ corruptedPacket = true; //Frame received with errors
+ }
+ else
+ {
+ NS_LOG_LOGIC("CORRECT! (" << this << ") (" << Simulator::Now().GetSeconds() << ") State: " << m_currentState);
+ corruptedPacket = false; //Frame received successfully
+ }
+
+ return corruptedPacket;
+}
+
+void HiddenMarkovErrorModel::DoReset (void)
+{
+ NS_LOG_FUNCTION_NOARGS();
+ m_currentState = 0;
+}
+
+bool HiddenMarkovErrorModel::ChangeState(void) {
+ NS_LOG_FUNCTION("Object" << this << "State" << m_currentState << "Time" << Simulator::Now().GetSeconds());
+ u_int16_t i, maxState;
+ double transitionProbability, max;
+ max = -1;
+ for (i = 0; (int) i < (m_transitionMatrix[m_currentState]).size(); i++) {
+ transitionProbability = (m_transitionMatrix[m_currentState])[i] * m_ranvar.GetValue();
+ //Different possibilities, depending on the type of simulation chosen:
+ //EU_TIME: One call to this method brings about necessarily a state change (called after every average state stay duration)
+ //Otherwise: As called at each frame reception, it may hold the same state
+ if (m_unit == EU_TIME) //&& (transitionProbability > max) && (i != m_currentState)) //Time-based --> MUST change state
+ {
+ if ((transitionProbability > max) && (i != m_currentState)) {
+ max = transitionProbability;
+ maxState = i;
+ }
+ } else {
+ if (transitionProbability > max) {
+ max = transitionProbability;
+ maxState = i;
+ }
+ }
+ }
+ //Did actually make a state change??
+ if (m_currentState != maxState) {
+ NS_LOG_DEBUG( "(" << m_currentState << ") --> (" << maxState << ") (" << this << ")" );
+ m_currentState = maxState;
+ return true;
+ }
+ return false;
+}
+
+void HiddenMarkovErrorModel::InitializeTimer()
+{
+ NS_LOG_FUNCTION(this);
+ double nextTimeout;
+ double nextTimeoutMeanValue;
+
+ //Set the next timeout
+ nextTimeoutMeanValue = m_meanDurationVector[m_currentState] * m_averageInterFrameDuration;
+ ExponentialVariable expVar(nextTimeoutMeanValue);
+ nextTimeout = expVar.GetValue();
+
+ NS_LOG_INFO("(" << Simulator::Now().GetSeconds() << ") - Next timeout " << nextTimeoutMeanValue \
+ << " --> " << nextTimeout << " (" << m_currentState << ")");
+ Simulator::Schedule(MicroSeconds(nextTimeout),&HiddenMarkovErrorModel::TimerHandler, this);
+}
+
+void HiddenMarkovErrorModel::TimerHandler()
+{
+ NS_LOG_FUNCTION(this << Simulator::Now().GetSeconds());
+ double nextTimeout;
+ double nextTimeoutMeanValue;
+
+ //Once the timeout is reached, check if the states changes
+
+ //Set the next timeout
+ nextTimeoutMeanValue = m_meanDurationVector[m_currentState] * m_averageInterFrameDuration;
+ ExponentialVariable expVar(nextTimeoutMeanValue);
+ nextTimeout = expVar.GetValue();
+
+ ChangeState();
+ NS_LOG_INFO("(" << Simulator::Now().GetSeconds() << ") - Next timeout " << nextTimeoutMeanValue \
+ << " --> " << nextTimeout << " (" << m_currentState << ")");
+ Simulator::Schedule(MicroSeconds(nextTimeout),&HiddenMarkovErrorModel::TimerHandler, this);
+}
+
+void HiddenMarkovErrorModel::SetRxCallback(HiddenMarkovErrorModelRxCallback_t callback)
+{
+ NS_LOG_FUNCTION_NOARGS();
+ m_rxCallback = callback;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
« no previous file with comments | « ns-3.13/src/hidden-markov-error-model/model/hidden-markov-error-model.h ('k') | ns-3.13/src/hidden-markov-error-model/waf » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b