Skip to content

Commit c19f396

Browse files
committed
[active-standby] support reset heartbeat suspend timer
Signed-off-by: Longxiang Lyu <[email protected]>
1 parent 927ee8a commit c19f396

17 files changed

+178
-3
lines changed

src/DbInterface.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <boost/bind/bind.hpp>
2929
#include <boost/date_time/gregorian/gregorian.hpp>
3030
#include <boost/lexical_cast.hpp>
31+
#include <boost/tokenizer.hpp>
3132

3233
#include "swss/netdispatcher.h"
3334
#include "swss/netlink.h"
@@ -1050,6 +1051,10 @@ void DbInterface::processMuxLinkmgrConfigNotifiction(std::deque<swss::KeyOpField
10501051
mMuxManagerPtr->processSrcMac(v == "ToRMac");
10511052
} else if (f == "interval_pck_loss_count_update") {
10521053
mMuxManagerPtr->setLinkProberStatUpdateIntervalCount(boost::lexical_cast<uint32_t> (v));
1054+
} else if (f == "reset_suspend_timer") {
1055+
boost::tokenizer<> tok(v);
1056+
std::vector<std::string> ports(tok.begin(), tok.end());
1057+
mMuxManagerPtr->processResetSuspendTimer(ports);
10531058
}
10541059

10551060
MUXLOGINFO(boost::format("key: %s, Operation: %s, f: %s, v: %s") %

src/MuxManager.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -598,4 +598,21 @@ void MuxManager::handleTsaEnableNotification(bool enable)
598598
}
599599
}
600600

601+
//
602+
// ---> processResetSuspendTimer
603+
//
604+
// process suspend timer reset requests
605+
//
606+
void MuxManager::processResetSuspendTimer(const std::vector<std::string> &portNames)
607+
{
608+
for (const std::string &portName : portNames)
609+
{
610+
MUXLOGINFO(boost::format("%s: reset heartbeat suspend timer") % portName);
611+
PortMapIterator portMapIterator = mPortMap.find(portName);
612+
if (portMapIterator != mPortMap.end()) {
613+
portMapIterator->second->handleResetSuspendTimer();
614+
}
615+
}
616+
}
617+
601618
} /* namespace mux */

src/MuxManager.h

+11
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,17 @@ class MuxManager
495495
*/
496496
void handleTsaEnableNotification(bool enable);
497497

498+
/**
499+
*@method processResetSuspendTimer
500+
*
501+
*@brief process suspend timer reset requests
502+
*
503+
*@param portNames (in) mux ports to reset the suspend timer
504+
*
505+
*@return none
506+
*/
507+
void processResetSuspendTimer(const std::vector<std::string> &portNames);
508+
498509
private:
499510
/**
500511
*@method getMuxPortCableType

src/MuxPort.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -437,4 +437,19 @@ void MuxPort::handleTsaEnable(bool enable)
437437
));
438438
}
439439

440+
//
441+
// ---> handleResetSuspendTimer();
442+
//
443+
// handle suspend timer reset
444+
//
445+
void MuxPort::handleResetSuspendTimer()
446+
{
447+
MUXLOGWARNING(boost::format("%s: reset heartbeat suspend timer") % mMuxPortConfig.getPortName());
448+
449+
boost::asio::post(mStrand, boost::bind(
450+
&link_manager::LinkManagerStateMachineBase::handleResetSuspendTimer,
451+
mLinkManagerStateMachinePtr.get()
452+
));
453+
}
454+
440455
} /* namespace mux */

src/MuxPort.h

+9
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,15 @@ class MuxPort: public std::enable_shared_from_this<MuxPort>
419419
*/
420420
void handleTsaEnable(bool enable);
421421

422+
/**
423+
*@method handleResetSuspendTimer
424+
*
425+
*@brief handle reset suspend timer request
426+
*
427+
* @return none
428+
*/
429+
void handleResetSuspendTimer();
430+
422431
protected:
423432
friend class test::MuxManagerTest;
424433
friend class test::FakeMuxPort;

src/link_manager/LinkManagerStateMachineActiveStandby.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,22 @@ void ActiveStandbyStateMachine::handleResetLinkProberPckLossCount()
958958
mResetIcmpPacketCountsFnPtr();
959959
}
960960

961+
// ---> handleResetSuspendTimer();
962+
//
963+
// reset the heartbeat suspend timer
964+
//
965+
void ActiveStandbyStateMachine::handleResetSuspendTimer()
966+
{
967+
MUXLOGDEBUG(boost::format("%s: reset heartbeat suspend timer") % mMuxPortConfig.getPortName());
968+
969+
if (ps(mCompositeState) == link_prober::LinkProberState::Label::Unknown &&
970+
ms(mCompositeState) == mux_state::MuxState::Label::Active &&
971+
ls(mCompositeState) == link_state::LinkState::Label::Up) {
972+
mUnknownActiveUpBackoffFactor = 1;
973+
mResumeTxFnPtr();
974+
}
975+
}
976+
961977
//
962978
// ---> updateMuxLinkmgrState();
963979
//

src/link_manager/LinkManagerStateMachineActiveStandby.h

+9
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,15 @@ class ActiveStandbyStateMachine: public LinkManagerStateMachineBase,
401401
*/
402402
void handleResetLinkProberPckLossCount();
403403

404+
/**
405+
* @method handleResetSuspendTimer
406+
*
407+
* @brief reset the heartbeat suspend timer
408+
*
409+
* @return none
410+
*/
411+
void handleResetSuspendTimer();
412+
404413
private:
405414
/**
406415
*@method updateMuxLinkmgrState

src/link_manager/LinkManagerStateMachineBase.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,15 @@ void LinkManagerStateMachineBase::handleResetLinkProberPckLossCount()
336336
MUXLOGINFO(mMuxPortConfig.getPortName());
337337
}
338338

339+
// ---> handleResetSuspendTimer();
340+
//
341+
// reset the heartbeat suspend timer
342+
//
343+
void LinkManagerStateMachineBase::handleResetSuspendTimer()
344+
{
345+
MUXLOGINFO(mMuxPortConfig.getPortName());
346+
}
347+
339348
//
340349
// ---> postMuxStateEvent(mux_state::MuxState::Label label)
341350
//

src/link_manager/LinkManagerStateMachineBase.h

+9
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,15 @@ class LinkManagerStateMachineBase : public common::StateMachine {
505505
*/
506506
virtual void handleResetLinkProberPckLossCount();
507507

508+
/**
509+
* @method handleResetSuspendTimer
510+
*
511+
* @brief reset the heartbeat suspend timer
512+
*
513+
* @return none
514+
*/
515+
virtual void handleResetSuspendTimer();
516+
508517
public:
509518
/**
510519
*@method getLinkProberStateMachinePtr

src/link_prober/LinkProber.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,9 @@ void LinkProber::startProbing()
188188
//
189189
void LinkProber::suspendTxProbes(uint32_t suspendTime_msec)
190190
{
191-
MUXLOGWARNING(boost::format("%s: suspend ICMP heartbeat probing") % mMuxPortConfig.getPortName());
191+
MUXLOGWARNING(boost::format("%s: suspend ICMP heartbeat probing %dms") % mMuxPortConfig.getPortName() % suspendTime_msec);
192192

193+
// NOTE: the timer reset also cancels any pending async ops with ec as boost::asio::error::operation_aborted
193194
mSuspendTimer.expires_from_now(boost::posix_time::milliseconds(suspendTime_msec));
194195
mSuspendTimer.async_wait(mStrand.wrap(boost::bind(
195196
&LinkProber::handleSuspendTimeout,
@@ -198,6 +199,7 @@ void LinkProber::suspendTxProbes(uint32_t suspendTime_msec)
198199
)));
199200

200201
mSuspendTx = true;
202+
mCancelSuspend = false;
201203
}
202204

203205
//
@@ -210,6 +212,7 @@ void LinkProber::resumeTxProbes()
210212
MUXLOGWARNING(boost::format("%s: resume ICMP heartbeat probing") % mMuxPortConfig.getPortName());
211213

212214
mSuspendTimer.cancel();
215+
mCancelSuspend = true;
213216
}
214217

215218
//
@@ -538,8 +541,8 @@ void LinkProber::handleSuspendTimeout(boost::system::error_code errorCode)
538541

539542
mSuspendTx = false;
540543

541-
if (errorCode == boost::system::errc::success) {
542-
// inform the composite state machine about Suspend timer expiry
544+
if (errorCode == boost::system::errc::success || mCancelSuspend) {
545+
// inform the composite state machine about Suspend timer expiry or cancel
543546
boost::asio::io_service::strand &strand = mLinkProberStateMachinePtr->getStrand();
544547
boost::asio::io_service &ioService = strand.context();
545548
ioService.post(strand.wrap(boost::bind(
@@ -549,6 +552,8 @@ void LinkProber::handleSuspendTimeout(boost::system::error_code errorCode)
549552
LinkProberStateMachineBase::getSuspendTimerExpiredEvent()
550553
)));
551554
}
555+
556+
mCancelSuspend = false;
552557
}
553558

554559
//

src/link_prober/LinkProber.h

+1
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ class LinkProber
629629
std::array<uint8_t, MUX_MAX_ICMP_BUFFER_SIZE> mTxBuffer;
630630
std::array<uint8_t, MUX_MAX_ICMP_BUFFER_SIZE> mRxBuffer;
631631

632+
bool mCancelSuspend = false;
632633
bool mSuspendTx = false;
633634
bool mShutdownTx = false;
634635
bool mDecreaseProbingInterval = false;

test/FakeMuxPort.h

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class FakeMuxPort : public ::mux::MuxPort {
7373

7474
link_prober::LinkProberState::Label getPeerLinkProberState() { return getActiveActiveStateMachinePtr()->mPeerLinkProberState; };
7575
mux_state::MuxState::Label getPeerMuxState() { return getActiveActiveStateMachinePtr()->mPeerMuxState; };
76+
uint32_t getActiveStandbyStateMachineSuspendBackoffFactor() { return getActiveStandbyStateMachinePtr()->mUnknownActiveUpBackoffFactor; }
7677

7778
inline void initLinkProberActiveActive();
7879
inline void initLinkProberActiveStandby();

test/LinkManagerStateMachineActiveActiveTest.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,12 @@ void LinkManagerStateMachineActiveActiveTest::handleMuxConfig(std::string config
223223
}
224224
}
225225

226+
void LinkManagerStateMachineActiveActiveTest::handleResetSuspendTimer(uint32_t count)
227+
{
228+
mFakeMuxPort.handleResetSuspendTimer();
229+
runIoService(count);
230+
}
231+
226232
void LinkManagerStateMachineActiveActiveTest::activateStateMachine(bool enable_feature_default_route)
227233
{
228234
mMuxConfig.enableDefaultRouteFeature(enable_feature_default_route);
@@ -1210,4 +1216,17 @@ TEST_F(LinkManagerStateMachineActiveActiveTest, StateMachineInitEventWithMultipl
12101216
EXPECT_EQ(mDbInterfacePtr->mSetMuxStateInvokeCount, 2);
12111217
}
12121218

1219+
TEST_F(LinkManagerStateMachineActiveActiveTest, ResetSuspendTimer)
1220+
{
1221+
setMuxActive();
1222+
1223+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mSuspendTxProbeCallCount, 0);
1224+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mResumeTxProbeCallCount, 2);
1225+
// reset suspend timer is NOOP for active-active composite state machine
1226+
handleResetSuspendTimer();
1227+
VALIDATE_STATE(Active, Active, Up);
1228+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mSuspendTxProbeCallCount, 0);
1229+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mResumeTxProbeCallCount, 2);
1230+
}
1231+
12131232
} /* namespace test */

test/LinkManagerStateMachineActiveActiveTest.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class LinkManagerStateMachineActiveActiveTest : public ::testing::Test
4343
void handleProbeMuxState(std::string, uint32_t count = 0);
4444
void handleLinkState(std::string linkState, uint32_t count = 0);
4545
void handleMuxConfig(std::string config, uint32_t count = 0, bool poll = false);
46+
void handleResetSuspendTimer(uint32_t count = 0);
4647
void activateStateMachine(bool enable_feature_default_route=false);
4748
void setMuxActive();
4849
void setMuxStandby();

test/LinkManagerStateMachineTest.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@ void LinkManagerStateMachineTest::handleMuxConfig(std::string config, uint32_t c
211211
runIoService(count);
212212
}
213213

214+
void LinkManagerStateMachineTest::handleResetSuspendTimer(uint32_t count)
215+
{
216+
mFakeMuxPort.handleResetSuspendTimer();
217+
runIoService(count);
218+
}
219+
214220
void LinkManagerStateMachineTest::activateStateMachine()
215221
{
216222
mFakeMuxPort.activateStateMachine();
@@ -1607,4 +1613,43 @@ TEST_F(LinkManagerStateMachineTest, DefaultRouteStateRaceCondition)
16071613
stopIoServiceThreaded();
16081614
}
16091615

1616+
TEST_F(LinkManagerStateMachineTest, ResetSuspendTimer)
1617+
{
1618+
setMuxActive();
1619+
1620+
// swss notification
1621+
handleMuxState("active", 3);
1622+
VALIDATE_STATE(Active, Active, Up);
1623+
1624+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mSuspendTxProbeCallCount, 0);
1625+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mResumeTxProbeCallCount, 1);
1626+
1627+
handleResetSuspendTimer();
1628+
1629+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mSuspendTxProbeCallCount, 0);
1630+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mResumeTxProbeCallCount, 1);
1631+
1632+
EXPECT_EQ(mDbInterfacePtr->mProbeMuxStateInvokeCount, 0);
1633+
EXPECT_EQ(mDbInterfacePtr->mGetMuxStateInvokeCount, 1);
1634+
postLinkProberEvent(link_prober::LinkProberState::Unknown, 2);
1635+
VALIDATE_STATE(Unknown, Active, Up);
1636+
EXPECT_EQ(mDbInterfacePtr->mProbeMuxStateInvokeCount, 0);
1637+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mSuspendTxProbeCallCount, 1);
1638+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mResumeTxProbeCallCount, 1);
1639+
EXPECT_EQ(mFakeMuxPort.getActiveStandbyStateMachineSuspendBackoffFactor(), 2);
1640+
1641+
handleResetSuspendTimer();
1642+
1643+
// once suspend timer is reset, the tx probe is resumed
1644+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mSuspendTxProbeCallCount, 1);
1645+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mResumeTxProbeCallCount, 2);
1646+
// the backoff factor is restored to 1
1647+
EXPECT_EQ(mFakeMuxPort.getActiveStandbyStateMachineSuspendBackoffFactor(), 1);
1648+
1649+
postSuspendTimerExpiredEvent(2);
1650+
VALIDATE_STATE(Unknown, Wait, Up);
1651+
EXPECT_EQ(mFakeMuxPort.mFakeLinkProber->mDetectLinkCallCount, 1);
1652+
EXPECT_EQ(mDbInterfacePtr->mProbeMuxStateInvokeCount, 1);
1653+
}
1654+
16101655
} /* namespace test */

test/LinkManagerStateMachineTest.h

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class LinkManagerStateMachineTest: public ::testing::Test
5151
void handleProbeMuxState(std::string, uint32_t count = 0);
5252
void handleLinkState(std::string linkState, uint32_t count = 0);
5353
void handleMuxConfig(std::string config, uint32_t count = 0);
54+
void handleResetSuspendTimer(uint32_t count = 0);
5455
void activateStateMachine();
5556
void setMuxActive();
5657
void setMuxStandby();

test/MuxManagerTest.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -903,9 +903,11 @@ TEST_F(MuxManagerTest, LinkmgrdConfig)
903903
{"LINK_PROBER", "SET", {{"interval_v4", "abc"}}},
904904
{"LINK_PROBER", "SET", {{"src_mac", "ToRMac"}}},
905905
{"LINK_PROBER", "SET", {{"interval_pck_loss_count_update", "900"}}},
906+
{"LINK_PROBER", "SET", {{"reset_suspend_timer", "Ethernet0"}}},
906907
{"MUXLOGGER", "SET", {{"log_verbosity", "warning"}}},
907908
};
908909
processMuxLinkmgrConfigNotifiction(entries);
910+
runIoService(2);
909911

910912
EXPECT_TRUE(getTimeoutIpv4_msec(port) == v4PorbeInterval);
911913
EXPECT_TRUE(getTimeoutIpv6_msec(port) == v6ProveInterval);

0 commit comments

Comments
 (0)