which can be used to add interfaces, list currently detected
interfaces and issue a re-detect procedure which updates the
interface configuration respectively. The re-detect procedure
- only adds newly discovered interfaces, without removing any
- previously detected interfaces.
+ only adds newly discovered interfaces and addresses, without
+ removing any previously detected interfaces or addresses.
(Gitlab #3144)
Kea 3.1.8 (development) released on April 29, 2026
----------------------------------
The :isccmd:`interface-redetect` command retrieves the list of detected interfaces
-after performing a re-detect procedure which only adds newly discovered interfaces,
-without removing any previously detected interfaces.
+after performing a re-detect procedure which only adds newly discovered interfaces
+and addresses, without removing any previously detected interfaces or addresses.
This command does not take any parameters."
.. isccmd:: list-commands
try {
// stop thread pool (if running)
MultiThreadingCriticalSection cs;
+ ReceiverCriticalSection rcs;
IfaceMgr::instance().detectIfaces(true);
} catch (const std::exception& ex) {
error = true;
// for option definitions. This is equivalent to committing empty container.
LibDHCP::setRuntimeOptionDefs(OptionDefSpaceContainer());
+ ReceiverCriticalSection rcs;
+
IfaceMgr::instance().detectIfaces(true);
// Answer will hold the result.
try {
// stop thread pool (if running)
MultiThreadingCriticalSection cs;
+ ReceiverCriticalSection rcs;
IfaceMgr::instance().detectIfaces(true);
} catch (const std::exception& ex) {
error = true;
// for option definitions. This is equivalent to committing empty container.
LibDHCP::setRuntimeOptionDefs(OptionDefSpaceContainer());
+ ReceiverCriticalSection rcs;
+
IfaceMgr::instance().detectIfaces(true);
// Answer will hold the result.
};
/// @brief RAII class creating a critical section for the receiver thread.
+///
+/// Node: Should be used outside IfaceMgr member functions as this might
+/// cause a deadlock then calling the members in the IfaceMgr constructor
+/// because this class uses IfaceMgr::instance() to access the singleton
+/// instance.
class ReceiverCriticalSection : public boost::noncopyable {
public:
///
/// Entering the critical section: if running, the receiver
/// is stopped not clearing the packet queue.
- ReceiverCriticalSection(IfaceMgr& iface_mgr)
- : iface_mgr_(iface_mgr), is_running_(iface_mgr.isDHCPReceiverRunning()) {
+ ReceiverCriticalSection()
+ : is_running_(IfaceMgr::instance().isDHCPReceiverRunning()) {
if (is_running_) {
- iface_mgr_.stopDHCPReceiver(false);
+ IfaceMgr::instance().stopDHCPReceiver(false);
}
}
/// Leaving the critical section: if it was running, the receiver
/// is started.
~ReceiverCriticalSection() {
- if (is_running_) {
- auto family = iface_mgr_.getFamily();
- iface_mgr_.startDHCPReceiver(family);
+ if (is_running_ && !IfaceMgr::instance().isDHCPReceiverRunning()) {
+ auto family = IfaceMgr::instance().getFamily();
+ IfaceMgr::instance().startDHCPReceiver(family);
}
}
private:
- /// @brief The IfaceMgr instance.
- IfaceMgr& iface_mgr_;
-
/// @brief Is running flag.
bool is_running_;
};
/// This is a BSD specific interface detection method.
void
IfaceMgr::detectIfaces(bool update_only) {
- ReceiverCriticalSection rcs(*this);
if (detect_callback_) {
if (!detect_callback_(update_only)) {
return;
/// Uses the socket-based netlink protocol to retrieve the list of interfaces
/// from the Linux kernel.
void IfaceMgr::detectIfaces(bool update_only) {
- ReceiverCriticalSection rcs(*this);
if (detect_callback_) {
if (!detect_callback_(update_only)) {
return;
ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4());
ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
{
- ReceiverCriticalSection rcs(IfaceMgr::instance());
+ ReceiverCriticalSection rcs;
+ ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+ ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4());
+ {
+ ReceiverCriticalSection rcs_deep;
+ ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+ ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4());
+ }
ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4());
}
ASSERT_TRUE(IfaceMgr::instance().isDHCPReceiverRunning());
ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4()->empty());
{
- ReceiverCriticalSection rcs(IfaceMgr::instance());
+ ReceiverCriticalSection rcs;
+ ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+ ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4()->empty());
+ {
+ ReceiverCriticalSection rcs_deep;
+ ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+ ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4()->empty());
+ }
ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4()->empty());
}
ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6());
ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
{
- ReceiverCriticalSection rcs(IfaceMgr::instance());
+ ReceiverCriticalSection rcs;
+ ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+ ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6());
+ {
+ ReceiverCriticalSection rcs_deep;
+ ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+ ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6());
+ }
ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6());
}
ASSERT_TRUE(IfaceMgr::instance().isDHCPReceiverRunning());
ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6()->empty());
{
- ReceiverCriticalSection rcs(IfaceMgr::instance());
+ ReceiverCriticalSection rcs;
+ ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+ ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6()->empty());
+ {
+ ReceiverCriticalSection rcs_deep;
+ ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+ ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6()->empty());
+ }
ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6()->empty());
}
const bool can_use_bcast, bool skip_opened) const {
MultiThreadingCriticalSection cs;
+ ReceiverCriticalSection rcs;
+
// The detection must be done before resetting and setting the
// inactive4_ and inactive6_ flags.
IfaceMgr::instance().detectIfaces(true);