summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp/tests/packet_queue6_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcp/tests/packet_queue6_unittest.cc')
-rw-r--r--src/lib/dhcp/tests/packet_queue6_unittest.cc295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/lib/dhcp/tests/packet_queue6_unittest.cc b/src/lib/dhcp/tests/packet_queue6_unittest.cc
new file mode 100644
index 0000000..52fb0dc
--- /dev/null
+++ b/src/lib/dhcp/tests/packet_queue6_unittest.cc
@@ -0,0 +1,295 @@
+// Copyright (C) 2018,2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dhcp/dhcp6.h>
+#include <dhcp/packet_queue_ring.h>
+#include <dhcp/tests/packet_queue_testutils.h>
+
+#include <boost/shared_ptr.hpp>
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::dhcp::test;
+
+namespace {
+
+/// @brief DHCPv6 queue with implements drop and eat logic
+///
+/// This class derives from the default DHCPv6 ring queue
+/// and provides implementations for shouldDropPacket() and
+/// eatPackets(). This permits a full exercising of the
+/// PacketQueue interface as well as the basic v6 ring queue
+/// mechanics.
+class TestQueue6 : public PacketQueueRing6 {
+public:
+ /// @brief Constructor
+ ///
+ /// @param queue_size maximum number of packets the queue can hold
+ TestQueue6(size_t queue_size)
+ : PacketQueueRing6("kea-ring6", queue_size), drop_enabled_(false), eat_count_(0) {
+ };
+
+ /// @brief virtual Destructor
+ virtual ~TestQueue6(){};
+
+ /// @brief Determines is a packet should be dropped.
+ ///
+ /// If drop is enabled and either the packet transaction
+ /// id or the socket source port are even numbers, drop the packet
+ ///
+ /// @param packet the packet under consideration
+ /// @param source the socket the packet came from
+ ///
+ /// @return True if the packet should be dropped.
+ virtual bool shouldDropPacket(Pkt6Ptr packet,
+ const SocketInfo& source) {
+ if (drop_enabled_) {
+ return ((packet->getTransid() % 2 == 0) ||
+ (source.port_ % 2 == 0));
+ }
+
+ return (false);
+ }
+
+ /// @brief Discards a number of packets from one end of the queue
+ ///
+ /// Dequeue and discard eat_count_ packets from the given end of
+ /// the queue_.
+ ///
+ /// @param from end of the queue from which packets should discarded
+ ///
+ /// @return The number of packets discarded.
+ virtual int eatPackets(const QueueEnd& from) {
+ int eaten = 0;
+ for ( ; eaten < eat_count_; ++eaten) {
+ Pkt6Ptr pkt = popPacket(from);
+ if (!pkt) {
+ break;
+ }
+ }
+
+ return (eaten);
+ }
+
+ bool drop_enabled_;
+ int eat_count_;
+};
+
+// Verifies use of the generic PacketQueue interface to
+// construct a queue implementation.
+TEST(PacketQueueRing6, interfaceBasics) {
+ // Verify we can create a queue
+ PacketQueue6Ptr q(new PacketQueueRing6("kea-ring6",100));
+ ASSERT_TRUE(q);
+
+ // It should be empty.
+ EXPECT_TRUE(q->empty());
+
+ // Type should match.
+ EXPECT_EQ("kea-ring6", q->getQueueType());
+
+ // Fetch the queue info and verify it has all the expected values.
+ checkInfo(q, "{ \"capacity\": 100, \"queue-type\": \"kea-ring6\", \"size\": 0 }");
+}
+
+// Verifies the higher level functions of queueing and dequeueing
+// from the ring buffer.
+TEST(PacketQueueRing6, enqueueDequeueTest) {
+ PacketQueue6Ptr q(new PacketQueueRing6("kea-ring6", 3));
+
+ // Fetch the queue info and verify it has all the expected values.
+ checkInfo(q, "{ \"capacity\": 3, \"queue-type\": \"kea-ring6\", \"size\": 0 }");
+
+ // Enqueue five packets. The first two should be pushed off.
+ SocketInfo sock1(isc::asiolink::IOAddress("127.0.0.1"), 777, 10);
+
+ for (int i = 1; i < 6; ++i) {
+ Pkt6Ptr pkt(new Pkt6(DHCPV6_SOLICIT, 1000+i));
+ ASSERT_NO_THROW(q->enqueuePacket(pkt, sock1));
+ }
+
+
+ // Fetch the queue info and verify it has all the expected values.
+ checkInfo(q, "{ \"capacity\": 3, \"queue-type\": \"kea-ring6\", \"size\": 3 }");
+
+ // We should have transids 1003,1004,1005
+ Pkt6Ptr pkt;
+ for (int i = 3; i < 6; ++i) {
+ ASSERT_NO_THROW(pkt = q->dequeuePacket());
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1000 + i, pkt->getTransid());
+ }
+
+ // Queue should be empty.
+ ASSERT_TRUE(q->empty());
+
+ // Dequeuing should fail safely, with an empty return.
+ ASSERT_NO_THROW(pkt = q->dequeuePacket());
+ ASSERT_FALSE(pkt);
+
+ // Enqueue three more packets.
+ for (int i = 0; i < 3; ++i) {
+ Pkt6Ptr pkt(new Pkt6(DHCPV6_SOLICIT, 1000+i));
+ ASSERT_NO_THROW(q->enqueuePacket(pkt, sock1));
+ }
+
+ checkIntStat(q, "size", 3);
+
+ // Let's flush the buffer and then verify it is empty.
+ q->clear();
+ EXPECT_TRUE(q->empty());
+ checkIntStat(q, "size", 0);
+}
+
+// Verifies peeking, pushing, and popping which
+// are unique to PacketQueueRing<> derivations.
+TEST(PacketQueueRing6, peekPushPopTest) {
+ PacketQueueRing6 q("kea-ring6", 3);
+
+ // Push five packets onto the end. The first two should get pushed off.
+ for (int i = 1; i < 6; ++i) {
+ Pkt6Ptr pkt(new Pkt6(DHCPV6_SOLICIT, 1000+i));
+ ASSERT_NO_THROW(q.pushPacket(pkt));
+ }
+
+ // We should have three.
+ ASSERT_EQ(3, q.getSize());
+
+ // We should have transids 1005,1004,1003 (back to front)
+
+ // Peek front should be transid 1003.
+ Pkt6Ptr pkt;
+ ASSERT_NO_THROW(pkt = q.peek(QueueEnd::FRONT));
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1003, pkt->getTransid());
+
+ // Peek back should be transid 1005.
+ ASSERT_NO_THROW(pkt = q.peek(QueueEnd::BACK));
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1005, pkt->getTransid());
+
+ // Pop front should return transid 1003.
+ ASSERT_NO_THROW(pkt = q.popPacket(QueueEnd::FRONT));
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1003, pkt->getTransid());
+
+ // Pop back should return transid 1005.
+ ASSERT_NO_THROW(pkt = q.popPacket(QueueEnd::BACK));
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1005, pkt->getTransid());
+
+ // Peek front should be transid 1004.
+ ASSERT_NO_THROW(pkt = q.peek(QueueEnd::FRONT));
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1004, pkt->getTransid());
+
+ // Peek back should be transid 1004.
+ ASSERT_NO_THROW(pkt = q.peek(QueueEnd::BACK));
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1004, pkt->getTransid());
+
+ // Pop front should return transid 1004.
+ ASSERT_NO_THROW(pkt = q.popPacket(QueueEnd::FRONT));
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1004, pkt->getTransid());
+
+ // Pop front should return an empty pointer.
+ ASSERT_NO_THROW(pkt = q.popPacket(QueueEnd::BACK));
+ ASSERT_FALSE(pkt);
+}
+
+// Verifies enqueuing operations when drop logic is enabled.
+// This accesses it's queue instance as a TestQueue6, rather than
+// a PacketQueue6Ptr, to provide access to TestQueue6 specifics.
+TEST(TestQueue6, shouldDropPacketTest) {
+ TestQueue6 q(100);
+ EXPECT_TRUE(q.empty());
+ ASSERT_FALSE(q.drop_enabled_);
+ ASSERT_EQ(0, q.eat_count_);
+
+ SocketInfo sock_even(isc::asiolink::IOAddress("127.0.0.1"), 888, 10);
+ SocketInfo sock_odd(isc::asiolink::IOAddress("127.0.0.1"), 777, 11);
+
+ // Drop is not enabled.
+ // We should be able to enqueue a packet with even numbered values.
+ Pkt6Ptr pkt(new Pkt6(DHCPV6_SOLICIT, 1002));
+ ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_even));
+ ASSERT_EQ(1, q.getSize());
+
+ // We should be able to enqueue a packet with odd numbered values.
+ pkt.reset(new Pkt6(DHCPV6_SOLICIT, 1003));
+ ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_odd));
+ ASSERT_EQ(2, q.getSize());
+
+ // Enable drop logic.
+ q.drop_enabled_ = true;
+
+ // We should not be able to add one with an even-numbered transid.
+ pkt.reset(new Pkt6(DHCPV6_SOLICIT, 1004));
+ ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_odd));
+ ASSERT_EQ(2, q.getSize());
+
+ // We should not be able to add one with from even-numbered port.
+ pkt.reset(new Pkt6(DHCPV6_SOLICIT, 1005));
+ ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_even));
+ EXPECT_EQ(2, q.getSize());
+
+ // We should be able to add one with an odd-numbered values.
+ pkt.reset(new Pkt6(DHCPV6_SOLICIT, 1007));
+ ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_odd));
+ EXPECT_EQ(3, q.getSize());
+
+ // Dequeue them and make sure they are as expected: 1002,1003, and 1007.
+ ASSERT_NO_THROW(pkt = q.dequeuePacket());
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1002, pkt->getTransid());
+
+ ASSERT_NO_THROW(pkt = q.dequeuePacket());
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1003, pkt->getTransid());
+
+ ASSERT_NO_THROW(pkt = q.dequeuePacket());
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1007, pkt->getTransid());
+
+ // Queue should be empty.
+ ASSERT_NO_THROW(pkt = q.dequeuePacket());
+ ASSERT_FALSE(pkt);
+}
+
+// Verifies dequeuing operations when eat packets is enabled.
+// This accesses it's queue instance as a TestQueue6, rather than
+// a PacketQueue6Ptr, to provide access to TestQueue6 specifics.
+TEST(TestQueue6, eatPacketsTest) {
+ TestQueue6 q(100);
+ EXPECT_TRUE(q.empty());
+ ASSERT_FALSE(q.drop_enabled_);
+ ASSERT_EQ(0, q.eat_count_);
+
+ SocketInfo sock(isc::asiolink::IOAddress("127.0.0.1"), 888, 10);
+
+ Pkt6Ptr pkt;
+ // Let's add five packets.
+ for (int i = 1; i < 6; ++i) {
+ pkt.reset(new Pkt6(DHCPV6_SOLICIT, 1000 + i));
+ ASSERT_NO_THROW(q.enqueuePacket(pkt, sock));
+ ASSERT_EQ(i, q.getSize());
+ }
+
+ // Setting eat count to two and dequeuing should discard 1001
+ // and 1002, resulting in a dequeue of 1003.
+ q.eat_count_ = 2;
+ ASSERT_NO_THROW(pkt = q.dequeuePacket());
+ ASSERT_TRUE(pkt);
+ EXPECT_EQ(1003, pkt->getTransid());
+ EXPECT_EQ(2, q.getSize());
+}
+
+} // end of anonymous namespace