Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
03defed4
Commit
03defed4
authored
Nov 07, 2016
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac5029'
parents
f7f06894
44ccccc9
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/tests/dhcp4_test_utils.cc
View file @
03defed4
...
...
@@ -19,6 +19,7 @@
#include
<dhcp/iface_mgr.h>
#include
<dhcp/tests/iface_mgr_test_config.h>
#include
<dhcp/tests/pkt_captures.h>
#include
<dhcpsrv/cfg_db_access.h>
#include
<dhcpsrv/cfgmgr.h>
#include
<dhcpsrv/lease.h>
#include
<dhcpsrv/lease_mgr.h>
...
...
@@ -608,6 +609,13 @@ Dhcpv4SrvTest::configure(const std::string& config, NakedDhcpv4Srv& srv,
ConstElementPtr
comment
=
config
::
parseAnswer
(
rcode
,
status
);
ASSERT_EQ
(
0
,
rcode
);
// Use specified lease database backend.
ASSERT_NO_THROW
(
{
CfgDbAccessPtr
cfg_db
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgDbAccess
();
cfg_db
->
setAppendedParameters
(
"universe=4"
);
cfg_db
->
createManagers
();
}
);
if
(
commit
)
{
CfgMgr
::
instance
().
commit
();
}
...
...
src/bin/dhcp4/tests/dora_unittest.cc
View file @
03defed4
...
...
@@ -13,6 +13,9 @@
#include
<dhcpsrv/host.h>
#include
<dhcpsrv/host_mgr.h>
#include
<dhcpsrv/subnet_id.h>
#include
<dhcpsrv/testutils/cql_schema.h>
#include
<dhcpsrv/testutils/mysql_schema.h>
#include
<dhcpsrv/testutils/pgsql_schema.h>
#include
<dhcp4/tests/dhcp4_test_utils.h>
#include
<dhcp4/tests/dhcp4_client.h>
#include
<boost/shared_ptr.hpp>
...
...
@@ -80,6 +83,18 @@ namespace {
/// - next-server = 10.0.0.7
/// - server name = "some-name.example.org"
/// - boot-file-name = "bootfile.efi"
///
/// - Configuration 7:
/// - Simple configuration with a single subnet and single pool
/// - Using MySQL lease database backend to store leases
///
/// - Configuration 8:
/// - Simple configuration with a single subnet and single pool
/// - Using PostgreSQL lease database backend to store leases
///
/// - Configuration 9:
/// - Simple configuration with a single subnet and single pool
/// - Using Cassandra lease database backend to store leases
const
char
*
DORA_CONFIGS
[]
=
{
// Configuration 0
"{
\"
interfaces-config
\"
: {"
...
...
@@ -262,6 +277,60 @@ const char* DORA_CONFIGS[] = {
" }"
" ]"
"} ]"
"}"
,
// Configuration 7
"{
\"
interfaces-config
\"
: {"
"
\"
interfaces
\"
: [
\"
*
\"
]"
"},"
"
\"
lease-database
\"
: {"
"
\"
type
\"
:
\"
mysql
\"
,"
"
\"
name
\"
:
\"
keatest
\"
,"
"
\"
user
\"
:
\"
keatest
\"
,"
"
\"
password
\"
:
\"
keatest
\"
"
"},"
"
\"
valid-lifetime
\"
: 600,"
"
\"
subnet4
\"
: [ { "
"
\"
subnet
\"
:
\"
10.0.0.0/24
\"
, "
"
\"
id
\"
: 1,"
"
\"
pools
\"
: [ {
\"
pool
\"
:
\"
10.0.0.10-10.0.0.100
\"
} ]"
" } ]"
"}"
,
// Configuration 8
"{
\"
interfaces-config
\"
: {"
"
\"
interfaces
\"
: [
\"
*
\"
]"
"},"
"
\"
lease-database
\"
: {"
"
\"
type
\"
:
\"
postgresql
\"
,"
"
\"
name
\"
:
\"
keatest
\"
,"
"
\"
user
\"
:
\"
keatest
\"
,"
"
\"
password
\"
:
\"
keatest
\"
"
"},"
"
\"
valid-lifetime
\"
: 600,"
"
\"
subnet4
\"
: [ { "
"
\"
subnet
\"
:
\"
10.0.0.0/24
\"
, "
"
\"
id
\"
: 1,"
"
\"
pools
\"
: [ {
\"
pool
\"
:
\"
10.0.0.10-10.0.0.100
\"
} ]"
" } ]"
"}"
,
// Configuration 9
"{
\"
interfaces-config
\"
: {"
"
\"
interfaces
\"
: [
\"
*
\"
]"
"},"
"
\"
lease-database
\"
: {"
"
\"
type
\"
:
\"
cql
\"
,"
"
\"
name
\"
:
\"
keatest
\"
,"
"
\"
user
\"
:
\"
keatest
\"
,"
"
\"
password
\"
:
\"
keatest
\"
"
"},"
"
\"
valid-lifetime
\"
: 600,"
"
\"
subnet4
\"
: [ { "
"
\"
subnet
\"
:
\"
10.0.0.0/24
\"
, "
"
\"
id
\"
: 1,"
"
\"
pools
\"
: [ {
\"
pool
\"
:
\"
10.0.0.10-10.0.0.100
\"
} ]"
" } ]"
"}"
};
...
...
@@ -318,6 +387,18 @@ public:
void
oneAllocationOverlapTest
(
const
std
::
string
&
clientid_a
,
const
std
::
string
&
clientid_b
);
/// @brief Test that the client using the same hardware address but
/// multiple client identifiers will obtain multiple leases.
///
/// This reflects the scenario of the OS installation over the network
/// when BIOS, installer and the host request DHCPv4 lease assignment
/// using the same MAC address/interface but generating different
/// client identifiers.
///
/// @param config_index Index of the configuration within the
/// @c DORA_CONFIGS array.
void
testMultiStageBoot
(
const
unsigned
int
config_index
);
/// @brief Interface Manager's fake configuration control.
IfaceMgrTestConfig
iface_mgr_test_config_
;
...
...
@@ -1374,4 +1455,186 @@ TEST_F(DORATest, statisticsNAK) {
EXPECT_EQ
(
1
,
pkt4_sent
->
getInteger
().
first
);
}
void
DORATest
::
testMultiStageBoot
(
const
unsigned
int
config_index
)
{
Dhcp4Client
client
(
Dhcp4Client
::
SELECTING
);
// Configure DHCP server.
ASSERT_NO_THROW
(
configure
(
DORA_CONFIGS
[
config_index
],
*
client
.
getServer
()));
// Stage 1: get the first lease for our client. In PXE boot, it would be
// a stage when the BIOS requests a lease.
// Include client id apart from the MAC address.
client
.
includeClientId
(
"10:21:32:AB:CD:EF"
);
ASSERT_NO_THROW
(
client
.
doDORA
());
// Make sure that the server responded.
ASSERT_TRUE
(
client
.
getContext
().
response_
);
Pkt4Ptr
resp
=
client
.
getContext
().
response_
;
// Make sure that the server has responded with DHCPACK.
ASSERT_EQ
(
DHCPACK
,
static_cast
<
int
>
(
resp
->
getType
()));
// Make sure that the client has got the lease which belongs
// to a pool.
IOAddress
leased_address1
=
client
.
config_
.
lease_
.
addr_
;
Subnet4Ptr
subnet
=
CfgMgr
::
instance
().
getCurrentCfg
()
->
getCfgSubnets4
()
->
selectSubnet
(
leased_address1
);
ASSERT_TRUE
(
subnet
);
// Make sure that the address has been allocated from the dynamic pool.
ASSERT_TRUE
(
subnet
->
inPool
(
Lease
::
TYPE_V4
,
leased_address1
));
// Stage 2: the client with a given MAC address has a lease in the
// lease database. The installer comes up and uses the same MAC address
// but generates a different client id. The server should treat the
// client with modified client identifier as a different client and
// create a new lease for it.
// Modify client identifier.
client
.
includeClientId
(
"11:54:45:AB:AA:FE"
);
ASSERT_NO_THROW
(
client
.
doDORA
());
// Make sure that the server responded.
ASSERT_TRUE
(
client
.
getContext
().
response_
);
resp
=
client
.
getContext
().
response_
;
// Make sure that the server has responded with DHCPACK.
ASSERT_EQ
(
DHCPACK
,
static_cast
<
int
>
(
resp
->
getType
()));
// Make sure that the client has got the lease which belongs
// to a pool.
IOAddress
leased_address2
=
client
.
config_
.
lease_
.
addr_
;
// Make sure that the address has been allocated from the dynamic pool.
ASSERT_TRUE
(
subnet
->
inPool
(
Lease
::
TYPE_V4
,
leased_address2
));
// The client should have got a new lease.
ASSERT_NE
(
leased_address1
,
leased_address2
);
// Modify client identifier again.
client
.
includeClientId
(
"22:34:AC:BE:44:54"
);
ASSERT_NO_THROW
(
client
.
doDORA
());
// Make sure that the server responded.
ASSERT_TRUE
(
client
.
getContext
().
response_
);
resp
=
client
.
getContext
().
response_
;
// Make sure that the server has responded with DHCPACK.
ASSERT_EQ
(
DHCPACK
,
static_cast
<
int
>
(
resp
->
getType
()));
// Make sure that the client has got the lease which belongs
// to a pool.
IOAddress
leased_address3
=
client
.
config_
.
lease_
.
addr_
;
// Make sure that the address has been allocated from the dynamic pool.
ASSERT_TRUE
(
subnet
->
inPool
(
Lease
::
TYPE_V4
,
leased_address3
));
// The client should have got a new lease.
ASSERT_NE
(
leased_address1
,
leased_address3
);
ASSERT_NE
(
leased_address2
,
leased_address3
);
}
// Test that the client using the same hardware address but multiple
// client identifiers will obtain multiple leases.
TEST_F
(
DORATest
,
multiStageBoot
)
{
// DORA_CONFIGS[0] to be used for server configuration.
testMultiStageBoot
(
0
);
}
// Starting tests which require MySQL backend availability. Those tests
// will not be executed if Kea has been compiled without the
// --with-dhcp-mysql.
#ifdef HAVE_MYSQL
/// @brief Test fixture class for the test utilizing MySQL database backend.
class
DORAMySQLTest
:
public
DORATest
{
public:
/// @brief Constructor.
///
/// Recreats MySQL schema for a test.
DORAMySQLTest
()
:
DORATest
()
{
destroyMySQLSchema
();
createMySQLSchema
();
}
/// @brief Destructor.
///
/// Destroys MySQL schema.
virtual
~
DORAMySQLTest
()
{
destroyMySQLSchema
();
}
};
// Test that the client using the same hardware address but multiple
// client identifiers will obtain multiple leases (MySQL lease database).
TEST_F
(
DORAMySQLTest
,
multiStageBoot
)
{
// DORA_CONFIGS[7] to be used for server configuration.
testMultiStageBoot
(
7
);
}
#endif
// Starting tests which require MySQL backend availability. Those tests
// will not be executed if Kea has been compiled without the
// --with-dhcp-pgsql.
#ifdef HAVE_PGSQL
/// @brief Test fixture class for the test utilizing PostgreSQL database backend.
class
DORAPgSQLTest
:
public
DORATest
{
public:
/// @brief Constructor.
///
/// Recreates PgSQL schema for a test.
DORAPgSQLTest
()
:
DORATest
()
{
destroyPgSQLSchema
();
createPgSQLSchema
();
}
/// @brief Destructor.
///
/// Destroys PgSQL schema.
virtual
~
DORAPgSQLTest
()
{
destroyPgSQLSchema
();
}
};
// Test that the client using the same hardware address but multiple
// client identifiers will obtain multiple leases (PostgreSQL lease database).
TEST_F
(
DORAPgSQLTest
,
multiStageBoot
)
{
// DORA_CONFIGS[8] to be used for server configuration.
testMultiStageBoot
(
8
);
}
#endif
#ifdef HAVE_CQL
/// @brief Test fixture class for the test utilizing Cassandra database backend.
class
DORACQLTest
:
public
DORATest
{
public:
/// @brief Constructor.
///
/// Recreates CQL schema for a test.
DORACQLTest
()
:
DORATest
()
{
destroyCqlSchema
(
false
,
true
);
createCqlSchema
(
false
,
true
);
}
/// @brief Destructor.
///
/// Destroys CQL schema.
virtual
~
DORACQLTest
()
{
destroyCqlSchema
(
false
,
true
);
}
};
// Test that the client using the same hardware address but multiple
// client identifiers will obtain multiple leases (CQL lease database).
TEST_F
(
DORACQLTest
,
multiStageBoot
)
{
// DORA_CONFIGS[9] to be used for server configuration.
testMultiStageBoot
(
9
);
}
#endif
}
// end of anonymous namespace
src/lib/dhcpsrv/alloc_engine.cc
View file @
03defed4
...
...
@@ -2150,13 +2150,21 @@ void findClientLease(const AllocEngine::ClientContext4& ctx, Lease4Ptr& client_l
// If no lease found using the client identifier, try the lookup using
// the HW address.
if
(
!
client_lease
&&
ctx
.
hwaddr_
)
{
client_lease
=
lease_mgr
.
getLease4
(
*
ctx
.
hwaddr_
,
ctx
.
subnet_
->
getID
());
// This lookup may return the lease which has conflicting client
// identifier and thus is considered to belong to someone else.
// If this is the case, we need to toss the result and force the
// Allocation Engine to allocate another lease.
if
(
client_lease
&&
!
client_lease
->
belongsToClient
(
ctx
.
hwaddr_
,
ctx
.
clientid_
))
{
client_lease
.
reset
();
// There may be cases when there is a lease for the same MAC address
// (even within the same subnet). Such situation may occur for PXE
// boot clients using the same MAC address but different client
// identifiers.
Lease4Collection
client_leases
=
lease_mgr
.
getLease4
(
*
ctx
.
hwaddr_
);
for
(
Lease4Collection
::
const_iterator
client_lease_it
=
client_leases
.
begin
();
client_lease_it
!=
client_leases
.
end
();
++
client_lease_it
)
{
Lease4Ptr
existing_lease
=
*
client_lease_it
;
if
((
existing_lease
->
subnet_id_
==
ctx
.
subnet_
->
getID
())
&&
existing_lease
->
belongsToClient
(
ctx
.
hwaddr_
,
ctx
.
clientid_
))
{
// Found the lease of this client, so return it.
client_lease
=
existing_lease
;
break
;
}
}
}
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment