From f079ed3f90f17d22f2d8c571a234ad610d0815b3 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 19 May 2018 14:39:50 +0200 Subject: [PATCH] [5549a] Ported unit tests --- src/bin/dhcp4/dhcp4_srv.cc | 2 +- src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 56 ++++++++++++++ src/bin/dhcp6/tests/classify_unittests.cc | 91 +++++++++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 149265a550..cd2aba14be 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -168,7 +168,7 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine, } // Perform second pass of classification. - Dhcpv4Srv::evaluateClasses(query, true); + Dhcpv4Srv::evaluateClasses(query, true); } const ClientClasses& classes = query_->getClasses(); diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index 324bd0f74c..7a31d989ce 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -2466,6 +2466,62 @@ TEST_F(Dhcpv4SrvTest, clientPoolClassify) { EXPECT_FALSE(offer->getYiaddr().isV4Zero()); } +// Checks if the KNOWN built-in class is indeed used for pool selection. +TEST_F(Dhcpv4SrvTest, clientPoolClassifyKnown) { + IfaceMgrTestConfig test_config(true); + IfaceMgr::instance().openSockets4(); + + NakedDhcpv4Srv srv(0); + + // This test configures 2 pools. + // The first one requires reservation, the second does the opposite. + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"client-classes\": [ {" + " \"name\": \"unknown\", " + " \"test\": \"not member('KNOWN')\" " + "} ]," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet4\": [ " + "{ \"pools\": [ { " + " \"pool\": \"192.0.2.1 - 192.0.2.100\", " + " \"client-class\": \"KNOWN\" }, " + " { \"pool\": \"192.0.3.1 - 192.0.3.100\", " + " \"client-class\": \"unknown\" } ], " + " \"subnet\": \"192.0.0.0/16\" } " + "]," + "\"valid-lifetime\": 4000 }"; + + ConstElementPtr json; + ASSERT_NO_THROW(json = parseDHCP4(config, true)); + + ConstElementPtr status; + EXPECT_NO_THROW(status = configureDhcp4Server(srv, json)); + + CfgMgr::instance().commit(); + + // check if returned status is OK + ASSERT_TRUE(status); + comment_ = config::parseAnswer(rcode_, status); + ASSERT_EQ(0, rcode_); + + // Create a simple packet that we'll use for classification + Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234)); + dis->setRemoteAddr(IOAddress("192.0.2.1")); + dis->setCiaddr(IOAddress("192.0.2.1")); + dis->setIface("eth0"); + OptionPtr clientid = generateClientId(); + dis->addOption(clientid); + + // First pool requires reservation so the second will be used + Pkt4Ptr offer = srv.processDiscover(dis); + ASSERT_TRUE(offer); + EXPECT_EQ(DHCPOFFER, offer->getType()); + EXPECT_EQ("192.0.3.1", offer->getYiaddr().toText()); +} + // Verifies last resort option 43 is backward compatible TEST_F(Dhcpv4SrvTest, option43LastResort) { IfaceMgrTestConfig test_config(true); diff --git a/src/bin/dhcp6/tests/classify_unittests.cc b/src/bin/dhcp6/tests/classify_unittests.cc index 5a5a6ffd17..771329f829 100644 --- a/src/bin/dhcp6/tests/classify_unittests.cc +++ b/src/bin/dhcp6/tests/classify_unittests.cc @@ -1085,6 +1085,97 @@ TEST_F(ClassifyTest, clientClassifyPool) { EXPECT_TRUE(ia_na3->getOption(D6O_IAADDR)); } +// Checks if the KNOWN built-in class is indeed used for pool selection. +TEST_F(ClassifyTest, clientClassifyPoolKnown) { + IfaceMgrTestConfig test_config(true); + + NakedDhcpv6Srv srv(0); + + // This test configures 2 pools. + // The first one requires reservation, the second does the opposite. + std::string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"client-classes\": [ {" + " \"name\": \"unknown\", " + " \"test\": \"not member('KNOWN')\" " + "} ]," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ " + " { \"pools\": [ " + " { " + " \"pool\": \"2001:db8:1::/64\", " + " \"client-class\": \"KNOWN\" " + " }, " + " { " + " \"pool\": \"2001:db8:2::/64\", " + " \"client-class\": \"unknown\" " + " } " + " ], " + " \"subnet\": \"2001:db8:2::/40\", " + " \"reservations\": [ " + " { \"duid\": \"01:02:03:04\", \"hostname\": \"foo\" } ] " + " } " + "], " + "\"valid-lifetime\": 4000 }"; + + ASSERT_NO_THROW(configure(config)); + + OptionPtr clientid1 = generateClientId(); + Pkt6Ptr query1 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); + query1->setRemoteAddr(IOAddress("2001:db8:1::3")); + query1->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000)); + query1->addOption(clientid1); + query1->setIface("eth1"); + + // First pool requires reservation so the second will be used + srv.classifyPacket(query1); + AllocEngine::ClientContext6 ctx1; + bool drop = false; + srv.initContext(query1, ctx1, drop); + ASSERT_FALSE(drop); + Pkt6Ptr response1 = srv.processSolicit(ctx1); + ASSERT_TRUE(response1); + OptionPtr ia_na1 = response1->getOption(D6O_IA_NA); + ASSERT_TRUE(ia_na1); + EXPECT_FALSE(ia_na1->getOption(D6O_STATUS_CODE)); + OptionPtr iaaddr1 = ia_na1->getOption(D6O_IAADDR); + ASSERT_TRUE(iaaddr1); + boost::shared_ptr addr1 = + boost::dynamic_pointer_cast(iaaddr1); + ASSERT_TRUE(addr1); + EXPECT_EQ("2001:db8:2::", addr1->getAddress().toText()); + + // Try with DUID 01:02:03:04 + uint8_t duid[] = { 0x01, 0x02, 0x03, 0x04 }; + OptionBuffer buf(duid, duid + sizeof(duid)); + OptionPtr clientid2(new Option(Option::V6, D6O_CLIENTID, buf)); + Pkt6Ptr query2 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 2345)); + query2->setRemoteAddr(IOAddress("2001:db8:1::3")); + query2->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000)); + query2->addOption(clientid2); + query2->setIface("eth1"); + + // Now the first pool will be used + srv.classifyPacket(query2); + AllocEngine::ClientContext6 ctx2; + srv.initContext(query2, ctx2, drop); + ASSERT_FALSE(drop); + Pkt6Ptr response2 = srv.processSolicit(ctx2); + ASSERT_TRUE(response2); + OptionPtr ia_na2 = response2->getOption(D6O_IA_NA); + ASSERT_TRUE(ia_na2); + EXPECT_FALSE(ia_na2->getOption(D6O_STATUS_CODE)); + OptionPtr iaaddr2 = ia_na2->getOption(D6O_IAADDR); + ASSERT_TRUE(iaaddr2); + boost::shared_ptr addr2 = + boost::dynamic_pointer_cast(iaaddr2); + ASSERT_TRUE(addr2); + EXPECT_EQ("2001:db8:1::", addr2->getAddress().toText()); +} + // Tests whether a packet with custom vendor-class (not erouter or docsis) // is classified properly. TEST_F(ClassifyTest, vendorClientClassification2) { -- 2.47.2