#include "psfp-flow-meter-instance.h" #include "ns3/log.h" #include "ns3/integer.h" #include "ns3/uinteger.h" #include "ns3/boolean.h" #include "ns3/simulator.h" #include "ns3/ethernet-header2.h" #include "ns3/ethernet-trailer.h" namespace ns3 { NS_LOG_COMPONENT_DEFINE("FlowMeterInstance"); NS_OBJECT_ENSURE_REGISTERED(FlowMeterInstance); TypeId FlowMeterInstance::GetTypeId() { static TypeId tid = TypeId("ns3::FlowMeterInstance") .SetParent() .SetGroupName("Tsn") .AddConstructor() .AddAttribute("CIR", "CIR parameter in bit/s", DataRateValue(DataRate("0Gb/s")), MakeDataRateAccessor(&FlowMeterInstance::m_cir), MakeDataRateChecker()) .AddAttribute("CBS", "CBS parameter in bit", UintegerValue(0), MakeUintegerAccessor(&FlowMeterInstance::m_cbs), MakeUintegerChecker()) .AddAttribute("EIR", "EIR parameter in bit/s", DataRateValue(DataRate("0Gb/s")), MakeDataRateAccessor(&FlowMeterInstance::m_eir), MakeDataRateChecker()) .AddAttribute("EBS", "EBS parameter in bit", UintegerValue(0), MakeUintegerAccessor(&FlowMeterInstance::m_ebs), MakeUintegerChecker()) .AddAttribute("DropOnYellow", "Drop on yellow function activation boolean", BooleanValue(false), MakeBooleanAccessor(&FlowMeterInstance::m_dropOnYellow), MakeBooleanChecker()) .AddAttribute("CF", "coupling flag boolean", BooleanValue(false), MakeBooleanAccessor(&FlowMeterInstance::m_cf), MakeBooleanChecker()) .AddAttribute("MarkAllFramesRedEnable", "MarkAllFramesRedEnable function activation boolean", BooleanValue(false), MakeBooleanAccessor(&FlowMeterInstance::m_markAllFramesRedEnable), MakeBooleanChecker()); return tid; } FlowMeterInstance::FlowMeterInstance() { NS_LOG_FUNCTION(this); m_lastTokenUpdateTime = Simulator::Now(); m_markAllFramesRed = false; } FlowMeterInstance::~FlowMeterInstance() { NS_LOG_FUNCTION(this); } bool FlowMeterInstance::Test(Ptr packet) { NS_LOG_FUNCTION(this); updateTokenBuckets(); Ptr payload = packet->Copy(); EthernetHeader2 ethHeader; EthernetTrailer trailer; payload->RemoveHeader(ethHeader); payload->RemoveTrailer(trailer); if (m_markAllFramesRed){ //Mark all frame = drop all NS_LOG_INFO("[PSFP] Packet #" << payload->GetUid() << " dropped due to markAllFrameRed"); return true; } NS_LOG_INFO("pkt size = " << payload->GetSize()); //First token bucket test if (payload->GetSize() <= m_committedToken) { //Mark green m_committedToken -= payload->GetSize(); NS_LOG_INFO("[PSFP] Packet #" << payload->GetUid() << " marked green"); return false; } //Second token bucket test if (payload->GetSize() <= m_excessToken) { //Mark yellow m_excessToken -= payload->GetSize(); if(m_dropOnYellow){ NS_LOG_INFO("[PSFP] Packet #" << payload->GetUid() << " marked yellow and dropped"); return true; } else{ NS_LOG_INFO("[PSFP] Packet #" << payload->GetUid() << " marked yellow and passed"); return false; } } else{ //Mark red NS_LOG_INFO("[PSFP] Packet #" << payload->GetUid() << " marked red (committedToken=" << m_committedToken << ", need " << payload->GetSize() << " tokens to pass)"); if(m_markAllFramesRedEnable){ m_markAllFramesRed = true; } return true; } } void FlowMeterInstance::updateTokenBuckets() { NS_LOG_FUNCTION(this); uint16_t tokenOverflow = 0; Time sinceLastUpdate = Simulator::Now() - m_lastTokenUpdateTime; m_committedToken = m_committedToken + (sinceLastUpdate.GetSeconds() * m_cir.GetBitRate())/8.; if (m_committedToken > m_cbs){ if (m_cf){ tokenOverflow = m_committedToken - m_cbs; } m_committedToken = m_cbs; } m_excessToken = m_excessToken + (sinceLastUpdate.GetSeconds() * m_eir.GetBitRate())/8. + tokenOverflow; if (m_excessToken>m_ebs){ m_excessToken = m_ebs; } m_lastTokenUpdateTime = Simulator::Now(); NS_LOG_INFO("m_committedToken = " << m_committedToken); NS_LOG_INFO("m_excessToken = " << m_excessToken); } };