Skip to content

Commit 58d8aae

Browse files
authored
Enforce switch after config mux to active (#95)
Approach What is the motivation for this PR? After config mux state active EthernetXX, the first toggle might not be able to be succeeded as xcvrd has a chance to fail to setup the gRPC connection as the route changed by muxorch needs time to work. Signed-off-by: Longxiang Lyu [email protected] How did you do it? The state change sequence after linkmgrd boots up and receives a mux config active: (unknown, unknown, up) --> config mux active --> (unknown, active, up) --> mux state unknown[as xcvrd could not setup gRPC connection] --> (unknown, unknown, up) --> probe mux state, return unknown --> (unknown, unknown, up) Once linkmgrd reaches (unknown, unknown, up), it will keep probing the mux till xcvrd returns either active or standby: if the probe result is active, we need an extra toggle to active to let show mux status shows active. if the probe result is standby, we also need an extra toggle to active to notify the gRPC server the port is standby and let show mux status shows active. How did you verify/test it?
1 parent 600df46 commit 58d8aae

3 files changed

+126
-11
lines changed

src/link_manager/LinkManagerStateMachineActiveActive.cpp

+35-3
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ void ActiveActiveStateMachine::handleMuxStateNotification(mux_state::MuxState::L
163163
MUXLOGWARNING(boost::format("%s: state db mux state: %s") % mMuxPortConfig.getPortName() % mMuxStateName[label]);
164164

165165
mWaitTimer.cancel();
166+
mLastMuxStateNotification = label;
166167

167168
if (mComponentInitState.all()) {
168169
if (mMuxStateMachine.getWaitStateCause() != mux_state::WaitState::WaitStateCause::SwssUpdate) {
@@ -543,6 +544,15 @@ void ActiveActiveStateMachine::initializeTransitionFunctionTable()
543544
boost::placeholders::_1
544545
);
545546

547+
mStateTransitionHandler[link_prober::LinkProberState::Label::Unknown]
548+
[mux_state::MuxState::Label::Standby]
549+
[link_state::LinkState::Label::Up] =
550+
boost::bind(
551+
&ActiveActiveStateMachine::LinkProberUnknownMuxStandbyLinkUpTransitionFunction,
552+
this,
553+
boost::placeholders::_1
554+
);
555+
546556
mStateTransitionHandler[link_prober::LinkProberState::Label::Active]
547557
[mux_state::MuxState::Label::Unknown]
548558
[link_state::LinkState::Label::Up] =
@@ -621,9 +631,29 @@ void ActiveActiveStateMachine::LinkProberActiveMuxStandbyLinkUpTransitionFunctio
621631
void ActiveActiveStateMachine::LinkProberUnknownMuxActiveLinkUpTransitionFunction(CompositeState &nextState)
622632
{
623633
MUXLOGINFO(mMuxPortConfig.getPortName());
624-
switchMuxState(nextState, mux_state::MuxState::Label::Standby);
634+
if (mMuxPortConfig.getMode() == common::MuxPortConfig::Mode::Active && mLastMuxStateNotification != mux_state::MuxState::Label::Active) {
635+
// last switch mux state to active failed, try again
636+
switchMuxState(nextState, mux_state::MuxState::Label::Active, true);
637+
} else {
638+
switchMuxState(nextState, mux_state::MuxState::Label::Standby);
639+
}
625640
}
626641

642+
//
643+
// ---> LinkProberUnknownMuxStandbyLinkUpTransitionFunction(CompositeState &nextState);
644+
//
645+
// transition function when entering {LinkProberUnknown, MuxStandby, LinkUp} state
646+
//
647+
void ActiveActiveStateMachine::LinkProberUnknownMuxStandbyLinkUpTransitionFunction(CompositeState &nextState)
648+
{
649+
MUXLOGINFO(mMuxPortConfig.getPortName());
650+
if (mMuxPortConfig.getMode() == common::MuxPortConfig::Mode::Active && mLastMuxStateNotification != mux_state::MuxState::Label::Active) {
651+
// last switch mux state to active failed, try again
652+
switchMuxState(nextState, mux_state::MuxState::Label::Active, true);
653+
}
654+
}
655+
656+
627657
//
628658
// ---> LinkProberActiveMuxUnknownLinkUpTransitionFunction(CompositeState &nextState);
629659
//
@@ -781,10 +811,12 @@ void ActiveActiveStateMachine::enterPeerLinkProberState(link_prober::LinkProberS
781811
//
782812
void ActiveActiveStateMachine::switchMuxState(
783813
CompositeState &nextState,
784-
mux_state::MuxState::Label label
814+
mux_state::MuxState::Label label,
815+
bool forceSwitch
785816
)
786817
{
787-
if (mMuxPortConfig.getMode() == common::MuxPortConfig::Mode::Auto ||
818+
if (forceSwitch ||
819+
mMuxPortConfig.getMode() == common::MuxPortConfig::Mode::Auto ||
788820
mMuxPortConfig.getMode() == common::MuxPortConfig::Mode::Detached) {
789821
MUXLOGWARNING(
790822
boost::format("%s: Switching MUX state to '%s'") %

src/link_manager/LinkManagerStateMachineActiveActive.h

+19-8
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,15 @@ class ActiveActiveStateMachine : public LinkManagerStateMachineBase,
150150

151151
/**
152152
* @method handleDefaultRouteStateNotification(const DefaultRoute routeState)
153-
*
153+
*
154154
* @brief handle default route state notification from routeorch
155-
*
155+
*
156156
* @param routeState
157-
*
157+
*
158158
* @return none
159-
*/
159+
*/
160160
void handleDefaultRouteStateNotification(const DefaultRoute routeState) override;
161-
161+
162162
/**
163163
*@method handleGetServerMacNotification
164164
*
@@ -272,6 +272,15 @@ class ActiveActiveStateMachine : public LinkManagerStateMachineBase,
272272
*/
273273
void LinkProberUnknownMuxActiveLinkUpTransitionFunction(CompositeState &nextState);
274274

275+
/**
276+
* @method LinkProberUnknownMuxStandbyLinkUpTransitionFunction
277+
*
278+
* @brief transition function when entering {LinkProberUnknown, MuxStandby, LinkUp} state
279+
*
280+
* @param nextState reference to composite state
281+
*/
282+
void LinkProberUnknownMuxStandbyLinkUpTransitionFunction(CompositeState &nextState);
283+
275284
/**
276285
* @method LinkProberUnknownMuxUnknownLinkUpTransitionFunction
277286
*
@@ -374,8 +383,9 @@ class ActiveActiveStateMachine : public LinkManagerStateMachineBase,
374383
*
375384
* @param nextState reference to composite state
376385
* @param label new MuxState label to switch to
386+
* @param forceSwitch force switch mux state, used to match the driver state only
377387
*/
378-
inline void switchMuxState(CompositeState &nextState, mux_state::MuxState::Label label);
388+
inline void switchMuxState(CompositeState &nextState, mux_state::MuxState::Label label, bool forceSwitch = false);
379389

380390
/**
381391
* @method switchPeerMuxState
@@ -467,9 +477,9 @@ class ActiveActiveStateMachine : public LinkManagerStateMachineBase,
467477

468478
/**
469479
* @method shutdownOrRestartLinkProberOnDefaultRoute()
470-
*
480+
*
471481
* @brief shutdown or restart link prober based on default route state
472-
*
482+
*
473483
* @return none
474484
*/
475485
void shutdownOrRestartLinkProberOnDefaultRoute() override;
@@ -558,6 +568,7 @@ class ActiveActiveStateMachine : public LinkManagerStateMachineBase,
558568
private: // peer link prober state and mux state
559569
link_prober::LinkProberState::Label mPeerLinkProberState = link_prober::LinkProberState::Label::PeerWait;
560570
mux_state::MuxState::Label mPeerMuxState = mux_state::MuxState::Label::Wait;
571+
mux_state::MuxState::Label mLastMuxStateNotification = mux_state::MuxState::Label::Unknown;
561572

562573
private:
563574
uint32_t mMuxProbeBackoffFactor = 1;

test/LinkManagerStateMachineActiveActiveTest.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -496,4 +496,76 @@ TEST_F(LinkManagerStateMachineActiveActiveTest, LinkmgrdBootupSequenceHeartBeatF
496496
EXPECT_EQ(mDbInterfacePtr->mLastSetMuxState, mux_state::MuxState::Label::Active);
497497
}
498498

499+
TEST_F(LinkManagerStateMachineActiveActiveTest, LinkmgrdBootupSequenceMuxConfigActiveProbeActive)
500+
{
501+
activateStateMachine();
502+
VALIDATE_STATE(Wait, Wait, Down);
503+
504+
postLinkEvent(link_state::LinkState::Up);
505+
VALIDATE_STATE(Wait, Wait, Up);
506+
507+
postLinkProberEvent(link_prober::LinkProberState::Unknown, 3);
508+
VALIDATE_STATE(Unknown, Standby, Up);
509+
EXPECT_EQ(mDbInterfacePtr->mSetMuxStateInvokeCount, 1);
510+
EXPECT_EQ(mDbInterfacePtr->mLastSetMuxState, mux_state::MuxState::Label::Standby);
511+
512+
handleMuxState("unknown", 3);
513+
VALIDATE_STATE(Unknown, Unknown, Up);
514+
515+
handleMuxConfig("active", 1);
516+
VALIDATE_STATE(Unknown, Active, Up);
517+
EXPECT_EQ(mDbInterfacePtr->mSetMuxStateInvokeCount, 2);
518+
EXPECT_EQ(mDbInterfacePtr->mLastSetMuxState, mux_state::MuxState::Label::Active);
519+
520+
handleMuxState("unknown", 5);
521+
VALIDATE_STATE(Unknown, Unknown, Up);
522+
523+
handleProbeMuxState("unknown", 3);
524+
VALIDATE_STATE(Unknown, Unknown, Up);
525+
526+
// xcvrd now answers the mux probe
527+
handleProbeMuxState("active", 3);
528+
VALIDATE_STATE(Unknown, Active, Up);
529+
EXPECT_EQ(mDbInterfacePtr->mSetMuxStateInvokeCount, 3);
530+
EXPECT_EQ(mDbInterfacePtr->mLastSetMuxState, mux_state::MuxState::Label::Active);
531+
532+
handleMuxState("active", 3);
533+
VALIDATE_STATE(Unknown, Active, Up);
534+
}
535+
536+
TEST_F(LinkManagerStateMachineActiveActiveTest, LinkmgrdBootupSequenceMuxConfigActiveProbeStandby)
537+
{
538+
activateStateMachine();
539+
VALIDATE_STATE(Wait, Wait, Down);
540+
541+
postLinkEvent(link_state::LinkState::Up);
542+
VALIDATE_STATE(Wait, Wait, Up);
543+
544+
postLinkProberEvent(link_prober::LinkProberState::Unknown, 3);
545+
VALIDATE_STATE(Unknown, Standby, Up);
546+
EXPECT_EQ(mDbInterfacePtr->mSetMuxStateInvokeCount, 1);
547+
EXPECT_EQ(mDbInterfacePtr->mLastSetMuxState, mux_state::MuxState::Label::Standby);
548+
549+
handleMuxState("unknown", 3);
550+
VALIDATE_STATE(Unknown, Unknown, Up);
551+
552+
handleMuxConfig("active", 1);
553+
VALIDATE_STATE(Unknown, Active, Up);
554+
EXPECT_EQ(mDbInterfacePtr->mSetMuxStateInvokeCount, 2);
555+
EXPECT_EQ(mDbInterfacePtr->mLastSetMuxState, mux_state::MuxState::Label::Active);
556+
557+
handleMuxState("unknown", 5);
558+
VALIDATE_STATE(Unknown, Unknown, Up);
559+
560+
handleProbeMuxState("unknown", 3);
561+
VALIDATE_STATE(Unknown, Unknown, Up);
562+
563+
// xcvrd now answers the mux probe
564+
handleProbeMuxState("standby", 3);
565+
EXPECT_EQ(mDbInterfacePtr->mSetMuxStateInvokeCount, 3);
566+
EXPECT_EQ(mDbInterfacePtr->mLastSetMuxState, mux_state::MuxState::Label::Active);
567+
handleMuxState("active", 3);
568+
VALIDATE_STATE(Unknown, Active, Up);
569+
}
570+
499571
} /* namespace test */

0 commit comments

Comments
 (0)