# Update the lease to declined
sql="call sflqUpdateLease4(inet_aton($in_address), NULL, NULL, 3600, timestamp('$future'),\
- 1, 0, 0, NULL, 1, NULL, NULL, NULL, 0)";
+ 1, 0, 0, NULL, 1, NULL, NULL, NULL, 0, inet_aton($in_address),
+ timestamp('$future'))"
run_statement "sflqUpdateLease4 $in_address" "$sql"
# Verify lease is updated lease4 and but not present free_lease4
# Update the lease to be reclaimed.
sql="call sflqUpdateLease4(inet_aton($in_address), NULL, NULL, 3600, timestamp('$future'),\
- 1, 0, 0, NULL, 2, NULL, NULL, NULL, 0)";
+ 1, 0, 0, NULL, 2, NULL, NULL, NULL, 0, inet_aton($in_address),
+ timestamp('$future'))";
run_statement "sflqUpdateLease4 to reclaimed $in_address" "$sql"
# Verify lease is updated in lease4 and added to free_lease4
# Update the expired lease.
sql="call sflqUpdateLease4(inet_aton($in_address), NULL, NULL, 3600, timestamp('$expired'),\
- 1, 0, 0, NULL, 0, NULL, NULL, NULL, 0)";
+ 1, 0, 0, NULL, 0, NULL, NULL, NULL, 0, inet_aton($in_address),
+ timestamp('$expired'))";
run_statement "sflqUpdateLease4 update expired $in_address" "$sql"
# Verify lease is updated in lease4 and added to free_lease4
state="1"
sql="call sflqUpdateLease6($bin_address, $duid, 3600, timestamp('$future'),\
$subnet_id, 3600, $ltype, $iaid, 128, 0, 0,\
- NULL, NULL, 0, 0, $state, NULL, 0)"
+ NULL, NULL, 0, 0, $state, NULL, 0,\
+ $bin_address, timestamp('$future'))"
run_statement "sflqUpdateLease6 $in_address" "$sql"
# Verify lease is updated lease6 and but not present free_lease6
state="2"
sql="call sflqUpdateLease6($bin_address, $duid, 3600, timestamp('$future'),\
$subnet_id, 3600, $ltype, $iaid, 128, 0, 0,\
- NULL, NULL, 0, 0, $state, NULL, 0)"
+ NULL, NULL, 0, 0, $state, NULL, 0,\
+ $bin_address, timestamp('$future'))"
run_statement "sflqUpdateLease6 $in_address" "$sql"
# Verify lease is updated in lease6 and added to free_lease6
state=0
sql="call sflqUpdateLease6($bin_address, $duid, 3600, timestamp('$expired'),\
$subnet_id, 3600, $ltype, $iaid, 128, 0, 0,\
- NULL, NULL, 0, 0, $state, NULL, 0)"
+ NULL, NULL, 0, 0, $state, NULL, 0,\
+ $bin_address, timestamp('$expired'))"
run_statement "sflqUpdateLease6 $in_address" "$sql"
# Verify lease is updated in lease6 and added to free_lease6
"?, ?, ?, ?, ?)"},
{MySqlLeaseMgr::SFLQ_UPDATE_LEASE4,
"CALL sflqUpdateLease4(?, ?, ?, ?, ?, ?, ?, ?, ?, "
- "?, ?, ?, ?, ?)"},
+ "?, ?, ?, ?, ?, ?, ?)"},
{MySqlLeaseMgr::SFLQ_DELETE_LEASE4,
"CALL sflqDeleteLease4(?,?)"},
{MySqlLeaseMgr::SFLQ_INSERT_LEASE6,
"CALL sflqInsertLease6(?, ?, ?, ?, ?, ?, ?, ?, ?, "
"?, ?, ?, ?, ?, ?, ?, ?, ?)"},
{MySqlLeaseMgr::SFLQ_UPDATE_LEASE6,
- "CALL sflqUpdateLease6(?, ?, ?, ?, ?, ?, ?, ?, ?, "
+ "CALL sflqUpdateLease6(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
"?, ?, ?, ?, ?, ?, ?, ?, ?)"},
{MySqlLeaseMgr::SFLQ_DELETE_LEASE6,
"CALL sflqDeleteLease6(?, ?)"},
'random_allocator.cc',
'resource_handler.cc',
'sanity_checker.cc',
+ 'sflq_allocation_state.cc',
'sflq_allocator.cc',
'shared_network.cc',
'srv_config.cc',
'random_allocator.h',
'resource_handler.h',
'sanity_checker.h',
+ 'sflq_allocation_state.h',
'sflq_allocator.h',
'shared_network.h',
'srv_config.h',
if (network_data->contains("allocator")) {
auto allocator_type = getString(network_data, "allocator");
if ((allocator_type != "iterative") && (allocator_type != "random") &&
- (allocator_type != "flq")) {
+ (allocator_type != "flq") && (allocator_type != "shared-flq")) {
// Unsupported allocator type used.
- isc_throw(DhcpConfigError, "supported allocators are: iterative, random and flq");
+ isc_throw(DhcpConfigError, "supported allocators are: iterative, "
+ "random, flq and shared-flq");
}
network->setAllocatorType(allocator_type);
}
if (network_data->contains("pd-allocator")) {
auto allocator_type = getString(network_data, "pd-allocator");
if ((allocator_type != "iterative") && (allocator_type != "random") &&
- (allocator_type != "flq")) {
+ (allocator_type != "flq") && (allocator_type != "shared-flq")) {
// Unsupported allocator type used.
- isc_throw(DhcpConfigError, "supported allocators are: iterative, random and flq");
+ isc_throw(DhcpConfigError, "supported allocators are: iterative, "
+ "random, flq and shared-flq");
}
network->setPdAllocatorType(allocator_type);
}
isc_throw(BadValue, "Free Lease Queue allocator is not supported for IPv6 address pools");
}
+ /// @todo Do we want this or not? One potential use case would be someone
+ /// using a mapped v4 addresses? "::xxxx:xxxx" -> "::192.0.2.1"
+ if (network->getAllocatorType() == "shared-flq") {
+ isc_throw(BadValue, "Shared FLQ allocator is not supported for IPv6 address pools");
+ }
+
// Parse prefix delegation allocator params.
auto network6 = boost::dynamic_pointer_cast<Network6>(shared_network);
parsePdAllocatorParams(shared_network_data, network6);
--- /dev/null
+// Copyright (C) 2026 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 <dhcpsrv/sflq_allocation_state.h>
+#include <util/multi_threading_mgr.h>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+using namespace isc::util;
+
+namespace isc {
+namespace dhcp {
+
+SubnetSflqAllocationState::SubnetSflqAllocationState()
+ : SubnetAllocationState() {
+}
+
+void
+SubnetSflqAllocationState::setLastAllocatedTime(boost::posix_time::ptime last_time
+ /* = not_a_date_time */) {
+ MultiThreadingLock lock(*mutex_);
+ if (last_time == boost::posix_time::not_a_date_time) {
+ setCurrentAllocatedTimeInternal();
+ } else {
+ last_allocated_time_ = last_time;
+ }
+}
+
+}
+}
--- /dev/null
+// Copyright (C) 2022-2023 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/.
+
+#ifndef SFQL_ALLOCATION_STATE_H
+#define SFQL_ALLOCATION_STATE_H
+
+#include <asiolink/io_address.h>
+#include <dhcpsrv/allocation_state.h>
+#include <dhcpsrv/lease.h>
+#include <dhcpsrv/subnet.h>
+#include <boost/shared_ptr.hpp>
+#include <cstdint>
+#include <map>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Forward declaration of the @c SubnetSflqAllocationState.
+class SubnetSflqAllocationState;
+
+/// @brief Type of the pointer to the @c SubnetSflqAllocationState.
+typedef boost::shared_ptr<SubnetSflqAllocationState> SubnetSflqAllocationStatePtr;
+
+/// @brief Subnet allocation state used by the shared-flq allocator.
+///
+/// It exposes the base class mechanism to store the last allocation time
+/// for various lease types. These times are used by the shared networks to
+/// find the "preferred" subnet (i.e., a subnet from which the latest lease
+/// was assigned).
+class SubnetSflqAllocationState : public SubnetAllocationState {
+public:
+
+#if 0
+ /// @brief Factory function creating the state instance from subnet.
+ ///
+ /// @param subnet instance of the subnet for which the allocation
+ /// state should be instantiated.
+ /// @return new allocation state instance.
+ static SubnetSflqAllocationStatePtr create(const SubnetPtr& subnet);
+#endif
+
+ /// @brief Constructor.
+ ///
+#if 0
+ /// @param prefix subnet prefix.
+ /// @param prefix_length subnet prefix length.
+ SubnetSflqAllocationState(const asiolink::IOAddress& prefix,
+ const uint8_t prefix_length);
+#else
+ SubnetSflqAllocationState();
+#endif
+
+ /// @brief Set last allocated time.
+ ///
+ /// @param last_time time of last allocation. If not specified
+ /// it is set to the current time.
+ void setLastAllocatedTime(boost::posix_time::ptime last_time =
+ boost::posix_time::not_a_date_time);
+};
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
+
+#endif // SFQL_ALLOCATION_STATE_H
.sflqPickFreeLease4(pool->getFirstAddress(),
pool->getLastAddress());
if (!free_lease.isV4Zero()) {
+ getSubnetState()->setLastAllocatedTime();
return (free_lease);
}
.sflqPickFreeLease6(pool->getFirstAddress(),
pool->getLastAddress());
if (!free_lease.isV6Zero()) {
+ getSubnetState()->setLastAllocatedTime();
return (free_lease);
}
.sflqPickFreeLease6(pool->getFirstAddress(),
pool->getLastAddress());
if (!free_lease.isV6Zero()) {
+ getSubnetState()->setLastAllocatedTime();
return (free_lease);
}
return (dist(generator_));
}
+SubnetSflqAllocationStatePtr
+SharedFlqAllocator::getSubnetState() const {
+ auto subnet = subnet_.lock();
+ if (!subnet->getAllocationState(pool_type_)) {
+ subnet->setAllocationState(Lease::TYPE_V4,
+ boost::make_shared<SubnetSflqAllocationState>());
+ }
+
+ return (boost::dynamic_pointer_cast<SubnetSflqAllocationState>
+ (subnet->getAllocationState(pool_type_)));
+}
+
} // end of namespace isc::dhcp
} // end of namespace isc
#define SFLQ_ALLOCATOR_H
#include <dhcpsrv/allocator.h>
+#include <dhcpsrv/sflq_allocation_state.h>
#include <dhcpsrv/lease.h>
#include <cstdint>
/// is using Shared FLQ allocation.
static bool inUse();
+ /// @brief Returns the allocation state for the subnet pool_type;
+ ///
+ /// @return The allocation state.
+ SubnetSflqAllocationStatePtr getSubnetState() const;
+
private:
/// @brief Performs allocator initialization after server's reconfiguration.
#include <dhcpsrv/iterative_allocator.h>
#include <dhcpsrv/random_allocation_state.h>
#include <dhcpsrv/random_allocator.h>
+#include <dhcpsrv/sflq_allocation_state.h>
+#include <dhcpsrv/sflq_allocator.h>
#include <dhcpsrv/shared_network.h>
#include <dhcpsrv/subnet.h>
#include <util/multi_threading_mgr.h>
for (auto const& pool : pools_) {
pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
}
-
+ } else if (allocator_type == "shared-flq") {
+ setAllocator(Lease::TYPE_V4,
+ boost::make_shared<SharedFlqAllocator>
+ (Lease::TYPE_V4, shared_from_this()));
+ setAllocationState(Lease::TYPE_V4,
+ boost::make_shared<SubnetSflqAllocationState>());
+ // Does not use pool level allocation states.
} else {
setAllocator(Lease::TYPE_V4,
boost::make_shared<IterativeAllocator>
boost::make_shared<FreeLeaseQueueAllocator>
(Lease::TYPE_PD, shared_from_this()));
setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr());
-
+ } else if (allocator_type == "shared-flq") {
+ setAllocator(Lease::TYPE_PD,
+ boost::make_shared<SharedFlqAllocator>
+ (Lease::TYPE_PD, shared_from_this()));
+ setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr());
} else {
setAllocator(Lease::TYPE_PD,
boost::make_shared<IterativeAllocator>
ASSERT_EQ(comment->getType(), Element::string);
EXPECT_EQ(1, rcode);
std::string expected = "Configuration parsing failed: ";
- expected += "supported allocators are: iterative, random and flq";
+ expected += "supported allocators are: iterative, random, flq and shared-flq";
EXPECT_EQ(expected, comment->stringValue());
}
ASSERT_EQ(comment->getType(), Element::string);
EXPECT_EQ(1, rcode);
std::string expected = "Configuration parsing failed: ";
- expected += "supported allocators are: iterative, random and flq";
+ expected += "supported allocators are: iterative, random, flq and shared-flq";
EXPECT_EQ(expected, comment->stringValue());
}
END $$
DELIMITER ;
+-- Procedure to create an affected rows count of 1.
+-- Used after udpate and delete lease operations.
+DROP TEMPORARY TABLE IF EXISTS sflq_dummy_row_count;
+DROP PROCEDURE IF EXISTS sflqFakeRowCount;
+DELIMITER $$
+CREATE PROCEDURE sflqFakeRowCount()
+BEGIN
+ IF (@sflq_dummy_exists IS NOT NULL)
+ THEN
+ UPDATE sflq_dummy_row_count SET dummy_val = NOT dummy_val;
+ ELSE
+ SET @sflq_dummy_exists = 1;
+ CREATE TEMPORARY TABLE sflq_dummy_row_count ( dummy_val TINYINT );
+ INSERT INTO sflq_dummy_row_count (dummy_val) VALUES (0);
+ END IF;
+END $$
+DELIMITER ;
+
-- Procedure to insert a v4 lease and update SFLQ data.
DROP PROCEDURE IF EXISTS sflqInsertLease4;
DELIMITER $$
IN p_remote_id VARBINARY(255),
IN p_pool_id INT UNSIGNED)
BEGIN
+ START TRANSACTION;
+
INSERT INTO lease4 (address, hwaddr, client_id, valid_lifetime, expire,
subnet_id, fqdn_fwd, fqdn_rev, hostname, state,
user_context, relay_id, remote_id, pool_id)
-- Delete it from the free queue. Ignore nothing deleted.
DELETE FROM free_lease4 WHERE address = p_address;
END IF;
+
+ COMMIT;
END $$
DELIMITER ;
IN p_user_context TEXT,
IN p_relay_id VARBINARY(255),
IN p_remote_id VARBINARY(255),
- IN p_pool_id INT UNSIGNED)
+ IN p_pool_id INT UNSIGNED,
+ IN p_where_address INT UNSIGNED,
+ IN p_where_expire TIMESTAMP)
BEGIN
+ DECLARE lease_row_count INT;
+
+ START TRANSACTION;
+
UPDATE lease4 SET address = p_address, hwaddr = p_hwaddr, client_id = p_client_id,
valid_lifetime = p_valid_lifetime, expire = p_expire,
subnet_id = p_subnet_id, fqdn_fwd = p_fqdn_fwd,
fqdn_rev = p_fqdn_rev, hostname = p_hostname, state = p_state,
user_context = p_user_context, relay_id = p_relay_id,
remote_id = p_remote_id, pool_id = p_pool_id
- WHERE (address = p_address and expire = p_expire);
+ WHERE (address = p_where_address and expire = p_where_expire);
+
+ -- Remember the lease affected row count.
+ SET lease_row_count = row_count();
-- Update SFLQ data.
-- If it is expired or expired-reclaimed add it to the free lease queue
THEN
-- Insert into free queue. Ignore duplicates.
INSERT INTO free_lease4 (address) VALUES (p_address)
- ON DUPLICATE KEY UPDATE address = p_address;
+ ON DUPLICATE KEY UPDATE address = p_address;
ELSE
-- Delete it from the free queue. Ignore nothing deleted.
DELETE FROM free_lease4 WHERE address = p_address;
END IF;
+
+ COMMIT;
+
+ -- If lease was updated but SFLQ logic changed no rows
+ -- force affected row count back to 1.
+ IF (lease_row_count > 0)
+ THEN
+ CALL sflqFakeRowCount();
+ END IF;
END $$
DELIMITER ;
IN p_address INT UNSIGNED,
IN p_expire TIMESTAMP)
BEGIN
+ DECLARE lease_row_count INT;
+
+ START TRANSACTION;
+
-- Delete the lease from lease4.
DELETE FROM lease4 WHERE address = p_address AND expire = p_expire;
+ -- Remember the lease affected row count.
+ SET lease_row_count = row_count();
+
-- If we didn't delete it either it was already gone or expire
-- didn't match. In case of the former it should already be in
-- the flq and in the latter, it should not be.
IF (row_count() > 0)
THEN
- -- Insert the lease into the free queue. Ignore duplicates.
INSERT INTO free_lease4 (address) VALUES (p_address)
ON DUPLICATE KEY UPDATE address = p_address;
END IF;
+
+ COMMIT;
+
+ -- If the lease was deleted but SFLQ logic changed no rows
+ -- force affected row count back to 1.
+ IF (lease_row_count > 0)
+ THEN
+ CALL sflqFakeRowCount();
+ END IF;
END $$
DELIMITER ;
IN p_user_context TEXT,
IN p_pool_id INT UNSIGNED)
BEGIN
+ START TRANSACTION;
+
INSERT INTO lease6 (address, duid, valid_lifetime, expire, subnet_id,
pref_lifetime, lease_type, iaid, prefix_len,
fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype,
-- Delete it from the free queue. Ignore nothing deleted.
DELETE FROM free_lease6 WHERE bin_address = p_address;
END IF;
+
+ COMMIT;
END $$
DELIMITER ;
IN p_hwaddr_source INT UNSIGNED,
IN p_state INT UNSIGNED,
IN p_user_context TEXT,
- IN p_pool_id INT UNSIGNED)
+ IN p_pool_id INT UNSIGNED,
+ IN p_where_address BINARY(16),
+ IN p_where_expire TIMESTAMP)
BEGIN
+ DECLARE lease_row_count INT;
+
+ START TRANSACTION;
+
UPDATE lease6 SET address = p_address, duid = p_duid, valid_lifetime = p_valid_lifetime,
expire = p_expire, subnet_id = p_subnet_id, pref_lifetime = p_pref_lifetime,
lease_type = p_lease_type, iaid = p_iaid, prefix_len = p_prefix_len,
fqdn_fwd = p_fqdn_fwd, fqdn_rev = p_fqdn_rev, hostname = p_hostname,
hwaddr = p_hwaddr, hwtype = p_hwtype, hwaddr_source = p_hwaddr_source,
state = p_state, user_context = p_user_context, pool_id = p_pool_id
- WHERE (address = p_address and expire = p_expire);
+ WHERE (address = p_where_address and expire = p_where_expire);
+
+ -- Remember the lease affected row count.
+ SET lease_row_count = row_count();
-- Update SFLQ data.
-- If it is expired or expired-reclaimed add it to the free lease queue
-- Delete it from the free queue. Ignore nothing deleted.
DELETE FROM free_lease6 WHERE bin_address = p_address;
END IF;
+
+ COMMIT;
+
+ -- If lease was updated but SFLQ logic changed no rows
+ -- force affected row count back to 1.
+ IF (lease_row_count > 0)
+ THEN
+ CALL sflqFakeRowCount();
+ END IF;
END $$
DELIMITER ;
IN p_address BINARY(16),
IN p_expire TIMESTAMP)
BEGIN
+ DECLARE lease_row_count INT;
+
+ START TRANSACTION;
+
-- Delete the lease from lease4.
DELETE FROM lease6 WHERE address = p_address AND expire = p_expire;
+ -- Remember the lease affected row count.
+ SET lease_row_count = row_count();
+
-- If we didn't delete it either it was already gone or expire
-- didn't match. In case of the former it should already be in
-- the flq and in the latter, it should not be.
VALUES (INET6_NTOA(p_address), p_address)
ON DUPLICATE KEY UPDATE bin_address = p_address;
END IF;
+
+ COMMIT;
+
+ -- If the lease was deleted but SFLQ logic changed no rows
+ -- force affected row count back to 1.
+ IF (lease_row_count > 0)
+ THEN
+ CALL sflqFakeRowCount();
+ END IF;
END $$
DELIMITER ;
END $$
DELIMITER ;
+-- Procedure to create an affected rows count of 1.
+-- Used after udpate and delete lease operations.
+DROP TEMPORARY TABLE IF EXISTS sflq_dummy_row_count;
+DROP PROCEDURE IF EXISTS sflqFakeRowCount;
+DELIMITER $$
+CREATE PROCEDURE sflqFakeRowCount()
+BEGIN
+ IF (@sflq_dummy_exists IS NOT NULL)
+ THEN
+ UPDATE sflq_dummy_row_count SET dummy_val = NOT dummy_val;
+ ELSE
+ SET @sflq_dummy_exists = 1;
+ CREATE TEMPORARY TABLE sflq_dummy_row_count ( dummy_val TINYINT );
+ INSERT INTO sflq_dummy_row_count (dummy_val) VALUES (0);
+ END IF;
+END $$
+DELIMITER ;
+
-- Procedure to insert a v4 lease and update SFLQ data.
DROP PROCEDURE IF EXISTS sflqInsertLease4;
DELIMITER $$
IN p_remote_id VARBINARY(255),
IN p_pool_id INT UNSIGNED)
BEGIN
+ START TRANSACTION;
+
INSERT INTO lease4 (address, hwaddr, client_id, valid_lifetime, expire,
subnet_id, fqdn_fwd, fqdn_rev, hostname, state,
user_context, relay_id, remote_id, pool_id)
-- Delete it from the free queue. Ignore nothing deleted.
DELETE FROM free_lease4 WHERE address = p_address;
END IF;
+
+ COMMIT;
END $$
DELIMITER ;
IN p_user_context TEXT,
IN p_relay_id VARBINARY(255),
IN p_remote_id VARBINARY(255),
- IN p_pool_id INT UNSIGNED)
+ IN p_pool_id INT UNSIGNED,
+ IN p_where_address INT UNSIGNED,
+ IN p_where_expire TIMESTAMP)
BEGIN
+ DECLARE lease_row_count INT;
+
+ START TRANSACTION;
+
UPDATE lease4 SET address = p_address, hwaddr = p_hwaddr, client_id = p_client_id,
valid_lifetime = p_valid_lifetime, expire = p_expire,
subnet_id = p_subnet_id, fqdn_fwd = p_fqdn_fwd,
fqdn_rev = p_fqdn_rev, hostname = p_hostname, state = p_state,
user_context = p_user_context, relay_id = p_relay_id,
remote_id = p_remote_id, pool_id = p_pool_id
- WHERE (address = p_address and expire = p_expire);
+ WHERE (address = p_where_address and expire = p_where_expire);
+
+ -- Remember the lease affected row count.
+ SET lease_row_count = row_count();
-- Update SFLQ data.
-- If it is expired or expired-reclaimed add it to the free lease queue
THEN
-- Insert into free queue. Ignore duplicates.
INSERT INTO free_lease4 (address) VALUES (p_address)
- ON DUPLICATE KEY UPDATE address = p_address;
+ ON DUPLICATE KEY UPDATE address = p_address;
ELSE
-- Delete it from the free queue. Ignore nothing deleted.
DELETE FROM free_lease4 WHERE address = p_address;
END IF;
+
+ COMMIT;
+
+ -- If lease was updated but SFLQ logic changed no rows
+ -- force affected row count back to 1.
+ IF (lease_row_count > 0)
+ THEN
+ CALL sflqFakeRowCount();
+ END IF;
END $$
DELIMITER ;
IN p_address INT UNSIGNED,
IN p_expire TIMESTAMP)
BEGIN
+ DECLARE lease_row_count INT;
+
+ START TRANSACTION;
+
-- Delete the lease from lease4.
DELETE FROM lease4 WHERE address = p_address AND expire = p_expire;
+ -- Remember the lease affected row count.
+ SET lease_row_count = row_count();
+
-- If we didn't delete it either it was already gone or expire
-- didn't match. In case of the former it should already be in
-- the flq and in the latter, it should not be.
IF (row_count() > 0)
THEN
- -- Insert the lease into the free queue. Ignore duplicates.
INSERT INTO free_lease4 (address) VALUES (p_address)
ON DUPLICATE KEY UPDATE address = p_address;
END IF;
+
+ COMMIT;
+
+ -- If the lease was deleted but SFLQ logic changed no rows
+ -- force affected row count back to 1.
+ IF (lease_row_count > 0)
+ THEN
+ CALL sflqFakeRowCount();
+ END IF;
END $$
DELIMITER ;
IN p_user_context TEXT,
IN p_pool_id INT UNSIGNED)
BEGIN
+ START TRANSACTION;
+
INSERT INTO lease6 (address, duid, valid_lifetime, expire, subnet_id,
pref_lifetime, lease_type, iaid, prefix_len,
fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype,
-- Delete it from the free queue. Ignore nothing deleted.
DELETE FROM free_lease6 WHERE bin_address = p_address;
END IF;
+
+ COMMIT;
END $$
DELIMITER ;
IN p_hwaddr_source INT UNSIGNED,
IN p_state INT UNSIGNED,
IN p_user_context TEXT,
- IN p_pool_id INT UNSIGNED)
+ IN p_pool_id INT UNSIGNED,
+ IN p_where_address BINARY(16),
+ IN p_where_expire TIMESTAMP)
BEGIN
+ DECLARE lease_row_count INT;
+
+ START TRANSACTION;
+
UPDATE lease6 SET address = p_address, duid = p_duid, valid_lifetime = p_valid_lifetime,
expire = p_expire, subnet_id = p_subnet_id, pref_lifetime = p_pref_lifetime,
lease_type = p_lease_type, iaid = p_iaid, prefix_len = p_prefix_len,
fqdn_fwd = p_fqdn_fwd, fqdn_rev = p_fqdn_rev, hostname = p_hostname,
hwaddr = p_hwaddr, hwtype = p_hwtype, hwaddr_source = p_hwaddr_source,
state = p_state, user_context = p_user_context, pool_id = p_pool_id
- WHERE (address = p_address and expire = p_expire);
+ WHERE (address = p_where_address and expire = p_where_expire);
+
+ -- Remember the lease affected row count.
+ SET lease_row_count = row_count();
-- Update SFLQ data.
-- If it is expired or expired-reclaimed add it to the free lease queue
-- Delete it from the free queue. Ignore nothing deleted.
DELETE FROM free_lease6 WHERE bin_address = p_address;
END IF;
+
+ COMMIT;
+
+ -- If lease was updated but SFLQ logic changed no rows
+ -- force affected row count back to 1.
+ IF (lease_row_count > 0)
+ THEN
+ CALL sflqFakeRowCount();
+ END IF;
END $$
DELIMITER ;
IN p_address BINARY(16),
IN p_expire TIMESTAMP)
BEGIN
+ DECLARE lease_row_count INT;
+
+ START TRANSACTION;
+
-- Delete the lease from lease4.
DELETE FROM lease6 WHERE address = p_address AND expire = p_expire;
+ -- Remember the lease affected row count.
+ SET lease_row_count = row_count();
+
-- If we didn't delete it either it was already gone or expire
-- didn't match. In case of the former it should already be in
-- the flq and in the latter, it should not be.
VALUES (INET6_NTOA(p_address), p_address)
ON DUPLICATE KEY UPDATE bin_address = p_address;
END IF;
+
+ COMMIT;
+
+ -- If the lease was deleted but SFLQ logic changed no rows
+ -- force affected row count back to 1.
+ IF (lease_row_count > 0)
+ THEN
+ CALL sflqFakeRowCount();
+ END IF;
END $$
DELIMITER ;