internet: (merge !129) Reduced event generation for Ipv4L3Protocol multicast de-duplication
This commit is contained in:
committed by
Tommaso Pecorella
parent
3b2ac47f2d
commit
204bb0d30e
@@ -80,6 +80,12 @@ Ipv4L3Protocol::GetTypeId (void)
|
||||
TimeValue (MilliSeconds (1)),
|
||||
MakeTimeAccessor (&Ipv4L3Protocol::m_expire),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("PurgeExpiredPeriod",
|
||||
"Time between purges of expired duplicate packet entries, "
|
||||
"0 means never purge",
|
||||
TimeValue (Seconds (1)),
|
||||
MakeTimeAccessor (&Ipv4L3Protocol::m_purge),
|
||||
MakeTimeChecker (Seconds (0)))
|
||||
.AddTraceSource ("Tx",
|
||||
"Send ipv4 packet to outgoing interface.",
|
||||
MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace),
|
||||
@@ -329,12 +335,9 @@ Ipv4L3Protocol::DoDispose (void)
|
||||
m_fragments.clear ();
|
||||
m_fragmentsTimers.clear ();
|
||||
|
||||
for (auto dup: m_dups)
|
||||
if (m_cleanDpd.IsRunning ())
|
||||
{
|
||||
if (dup.second.IsRunning ())
|
||||
{
|
||||
dup.second.Cancel ();
|
||||
}
|
||||
m_cleanDpd.Cancel ();
|
||||
}
|
||||
m_dups.clear ();
|
||||
|
||||
@@ -1763,14 +1766,21 @@ Ipv4L3Protocol::UpdateDuplicate (Ptr<const Packet> p, const Ipv4Header &header)
|
||||
bytes[8] = 0; // TTL
|
||||
bytes[10] = bytes[11] = 0; // Header checksum
|
||||
if (header.GetSerializedSize () > 20) // assume options should be 0'd
|
||||
std::fill_n (bytes.begin () + 20, header.GetSerializedSize () - 20, 0);
|
||||
|
||||
{
|
||||
std::fill_n (bytes.begin () + 20, header.GetSerializedSize () - 20, 0);
|
||||
}
|
||||
|
||||
// concat hash onto ID
|
||||
hash |= (uint64_t)Hash32 (bytes);
|
||||
}
|
||||
|
||||
// set cleanup job for new duplicate entries
|
||||
if (!m_cleanDpd.IsRunning () && m_purge.IsStrictlyPositive ())
|
||||
{
|
||||
m_cleanDpd = Simulator::Schedule (m_expire, &Ipv4L3Protocol::RemoveDuplicates, this);
|
||||
}
|
||||
|
||||
// assume this is a new entry
|
||||
bool isDup = false;
|
||||
DupTuple_t key {hash, proto, src, dst};
|
||||
NS_LOG_DEBUG ("Packet " << p->GetUid () << " key = (" <<
|
||||
std::hex << std::get<0> (key) << ", " <<
|
||||
@@ -1779,29 +1789,49 @@ Ipv4L3Protocol::UpdateDuplicate (Ptr<const Packet> p, const Ipv4Header &header)
|
||||
std::get<3> (key) << ")");
|
||||
|
||||
// place a new entry, on collision the existing entry iterator is returned
|
||||
auto iter = m_dups.emplace_hint (m_dups.end (), key, EventId ());
|
||||
// cancel un-expired event
|
||||
if (iter->second.IsRunning ())
|
||||
{
|
||||
iter->second.Cancel ();
|
||||
isDup = true; // flag this was a duplicate
|
||||
}
|
||||
DupMap_t::iterator iter;
|
||||
bool inserted, isDup;
|
||||
std::tie (iter, inserted) = m_dups.emplace (key, Seconds (0));
|
||||
isDup = !inserted && iter->second > Simulator::Now ();
|
||||
|
||||
// set the expiration event
|
||||
iter->second = Simulator::Schedule (m_expire, &Ipv4L3Protocol::RemoveDuplicate, this, iter);
|
||||
iter->second = Simulator::Now () + m_expire;
|
||||
return isDup;
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4L3Protocol::RemoveDuplicate (DupMap_t::const_iterator iter)
|
||||
Ipv4L3Protocol::RemoveDuplicates (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_LOGIC ("Remove key = (" <<
|
||||
std::hex << std::get<0> (iter->first) << ", " <<
|
||||
std::dec << +std::get<1> (iter->first) << ", " <<
|
||||
std::get<2> (iter->first) << ", " <<
|
||||
std::get<3> (iter->first) << ")");
|
||||
|
||||
m_dups.erase (iter);
|
||||
DupMap_t::size_type n = 0;
|
||||
Time expire = Simulator::Now ();
|
||||
auto iter = m_dups.cbegin ();
|
||||
while (iter != m_dups.cend ())
|
||||
{
|
||||
if (iter->second < expire)
|
||||
{
|
||||
NS_LOG_LOGIC ("Remove key = (" <<
|
||||
std::hex << std::get<0> (iter->first) << ", " <<
|
||||
std::dec << +std::get<1> (iter->first) << ", " <<
|
||||
std::get<2> (iter->first) << ", " <<
|
||||
std::get<3> (iter->first) << ")");
|
||||
iter = m_dups.erase (iter);
|
||||
++n;
|
||||
}
|
||||
else
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG ("Purged " << n << " expired duplicate entries out of " << (n + m_dups.size ()));
|
||||
|
||||
// keep cleaning up if necessary
|
||||
if (!m_dups.empty () && m_purge.IsStrictlyPositive ())
|
||||
{
|
||||
m_cleanDpd = Simulator::Schedule (m_purge, &Ipv4L3Protocol::RemoveDuplicates, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -560,8 +560,8 @@ private:
|
||||
/// IETF RFC 6621, Section 6.2 de-duplication w/o IPSec
|
||||
/// RFC 6621 recommended duplicate packet tuple: {IPV hash, IP protocol, IP source address, IP destination address}
|
||||
typedef std::tuple <uint64_t, uint8_t, Ipv4Address, Ipv4Address> DupTuple_t;
|
||||
/// Maps packet duplicate tuple to expiration event
|
||||
typedef std::map<DupTuple_t, EventId> DupMap_t;
|
||||
/// Maps packet duplicate tuple to expiration time
|
||||
typedef std::map<DupTuple_t, Time> DupMap_t;
|
||||
|
||||
/**
|
||||
* Registers duplicate entry, return false if new
|
||||
@@ -574,12 +574,13 @@ private:
|
||||
* Remove duplicate packet entry
|
||||
* \param [in] iter Iterator into duplicate map to remove
|
||||
*/
|
||||
void RemoveDuplicate (DupMap_t::const_iterator iter);
|
||||
|
||||
bool m_enableDpd; //!< Enable multicast duplicate packet detection
|
||||
DupMap_t m_dups; //!< map of packet duplicate tuples to expiry event
|
||||
Time m_expire; //!< duplicate entry expiration delay
|
||||
void RemoveDuplicates (void);
|
||||
|
||||
bool m_enableDpd; //!< Enable multicast duplicate packet detection
|
||||
DupMap_t m_dups; //!< map of packet duplicate tuples to expiry event
|
||||
Time m_expire; //!< duplicate entry expiration delay
|
||||
Time m_purge; //!< time between purging expired duplicate entries
|
||||
EventId m_cleanDpd; //!< event to cleanup expired duplicate entries
|
||||
};
|
||||
|
||||
} // Namespace ns3
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/config.h"
|
||||
|
||||
@@ -49,6 +50,7 @@
|
||||
#include "ns3/ipv4-static-routing-helper.h"
|
||||
#include "ns3/ipv4-address-helper.h"
|
||||
#include "ns3/simple-net-device-helper.h"
|
||||
#include "ns3/on-off-helper.h"
|
||||
|
||||
#include "ns3/traffic-control-layer.h"
|
||||
|
||||
@@ -356,6 +358,11 @@ Ipv4DeduplicationTest::DoRun (void)
|
||||
socket->SetAllowBroadcast (true);
|
||||
NS_TEST_EXPECT_MSG_EQ (socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), 1234)), 0,
|
||||
"Could not bind socket for node " << Names::FindName (*iter));
|
||||
|
||||
auto udpSocket = socket->GetObject<UdpSocket> ();
|
||||
udpSocket->MulticastJoinGroup (0, Ipv4Address (targetAddr.c_str ())); // future proof?
|
||||
udpSocket->SetAttribute ("IpMulticastTtl", StringValue ("4"));
|
||||
|
||||
socket->SetRecvCallback (MakeCallback (&Ipv4DeduplicationTest::ReceivePkt, this));
|
||||
sockets.push_back (socket);
|
||||
}
|
||||
@@ -366,9 +373,6 @@ Ipv4DeduplicationTest::DoRun (void)
|
||||
|
||||
// start TX from A
|
||||
auto txSocket = sockets.front ();
|
||||
auto udpSocket = txSocket->GetObject<UdpSocket> ();
|
||||
udpSocket->MulticastJoinGroup (0, Ipv4Address (targetAddr.c_str ())); // future proof?
|
||||
udpSocket->SetAttribute ("IpMulticastTtl", StringValue ("4"));
|
||||
|
||||
// ------ Now the tests ------------
|
||||
|
||||
@@ -497,3 +501,125 @@ Ipv4DeduplicationTestSuite::Ipv4DeduplicationTestSuite ()
|
||||
|
||||
static Ipv4DeduplicationTestSuite g_ipv4DeduplicationTestSuite; //!< Static variable for test initialization
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup internet-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief IPv4 Deduplication Performance Test
|
||||
*
|
||||
* This test case sets up a fully connected network of
|
||||
* 10 nodes. Each node transmits 2 packets / second
|
||||
* for about 20 seconds. Packets are relayed from
|
||||
* every receiver. The test outputs the number of
|
||||
* events that have been processed during the course
|
||||
* of the simulation. Test runtime is also a metric.
|
||||
*
|
||||
* The de-duplication cache entry expiration algorithm
|
||||
* has evolved from an event-per-expiry (EPE) algorithm to
|
||||
* a periodic event, batch purge (PBP) algorithm. The
|
||||
* current metrics are taken from tests on the development
|
||||
* box. Periodic batch purge period defaults to 1s.
|
||||
*
|
||||
* Events Runtime
|
||||
* EVE 656140 29s
|
||||
* PBP 337420 29s
|
||||
*
|
||||
*/
|
||||
class Ipv4DeduplicationPerformanceTest : public TestCase
|
||||
{
|
||||
public:
|
||||
Ipv4DeduplicationPerformanceTest (void);
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
Ipv4DeduplicationPerformanceTest::Ipv4DeduplicationPerformanceTest ()
|
||||
: TestCase ("Ipv4Deduplication performance test")
|
||||
{}
|
||||
|
||||
void
|
||||
Ipv4DeduplicationPerformanceTest::DoRun (void)
|
||||
{
|
||||
// multicast target
|
||||
const std::string targetAddr = "239.192.100.1";
|
||||
Config::SetDefault ("ns3::Ipv4L3Protocol::EnableDuplicatePacketDetection", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::Ipv4L3Protocol::DuplicateExpire", TimeValue (Time ("10s")));
|
||||
|
||||
// Create nodes
|
||||
auto nodes = NodeContainer ();
|
||||
nodes.Create (20);
|
||||
|
||||
SimpleNetDeviceHelper simplenet;
|
||||
auto devices = simplenet.Install (nodes);
|
||||
|
||||
Ipv4ListRoutingHelper listRouting;
|
||||
Ipv4StaticRoutingHelper staticRouting;
|
||||
listRouting.Add (staticRouting, 0);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.SetIpv6StackInstall (false);
|
||||
internet.SetIpv4ArpJitter (true);
|
||||
internet.SetRoutingHelper (listRouting);
|
||||
internet.Install (nodes);
|
||||
|
||||
Ipv4AddressHelper ipv4address;
|
||||
ipv4address.SetBase ("10.0.0.0", "255.255.255.0");
|
||||
ipv4address.Assign (devices);
|
||||
|
||||
// add static routes for each node / device
|
||||
auto diter = devices.Begin ();
|
||||
for (auto end = nodes.End (),
|
||||
iter = nodes.Begin (); iter != end; ++iter)
|
||||
{
|
||||
// route for forwarding
|
||||
staticRouting.AddMulticastRoute (*iter, Ipv4Address::GetAny (), targetAddr.c_str (), *diter, NetDeviceContainer (*diter));
|
||||
|
||||
// route for host
|
||||
// Use host routing entry according to note in Ipv4StaticRouting::RouteOutput:
|
||||
//// Note: Multicast routes for outbound packets are stored in the
|
||||
//// normal unicast table. An implication of this is that it is not
|
||||
//// possible to source multicast datagrams on multiple interfaces.
|
||||
//// This is a well-known property of sockets implementation on
|
||||
//// many Unix variants.
|
||||
//// So, we just log it and fall through to LookupStatic ()
|
||||
auto ipv4 = (*iter)->GetObject <Ipv4> ();
|
||||
NS_ASSERT_MSG ((bool) ipv4, "Node " << (*iter)->GetId () << " does not have Ipv4 aggregate");
|
||||
auto routing = staticRouting.GetStaticRouting (ipv4);
|
||||
routing->AddHostRouteTo (targetAddr.c_str (), ipv4->GetInterfaceForDevice (*diter), 0);
|
||||
|
||||
++diter;
|
||||
}
|
||||
|
||||
// Create application
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory", InetSocketAddress (targetAddr.c_str (), 1234));
|
||||
onoff.SetConstantRate (DataRate ("8kbps")); // 2 packets / second for default 512B packets
|
||||
onoff.SetAttribute ("MaxBytes", UintegerValue (512 * 40)); // 20 seconds worth of packets
|
||||
auto apps = onoff.Install (nodes);
|
||||
|
||||
apps.StartWithJitter (Seconds (4), CreateObjectWithAttributes <UniformRandomVariable> ("Max", DoubleValue (4)));
|
||||
|
||||
Simulator::Run ();
|
||||
NS_LOG_UNCOND ("Executed " << Simulator::GetEventCount () << " events");
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup internet-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief IPv4 Deduplication Performance TestSuite
|
||||
*/
|
||||
class Ipv4DeduplicationPerformanceTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
Ipv4DeduplicationPerformanceTestSuite ();
|
||||
};
|
||||
|
||||
Ipv4DeduplicationPerformanceTestSuite::Ipv4DeduplicationPerformanceTestSuite ()
|
||||
: TestSuite ("ipv4-deduplication-performance", PERFORMANCE)
|
||||
{
|
||||
AddTestCase (new Ipv4DeduplicationPerformanceTest, TestCase::EXTENSIVE);
|
||||
}
|
||||
|
||||
static Ipv4DeduplicationPerformanceTestSuite g_ipv4DeduplicationPerformanceTestSuite; //!< Static variable for test initialization
|
||||
|
||||
Reference in New Issue
Block a user