Skip to content

Commit cb29d7f

Browse files
authored
[ssw][ha] haorch consumes dpu_ appl_db to create bfd passive sessions on DPU (#3790)
What I did [ssw][ha] haorch consumes dpu_ appl_db to create bfd passive sessions on DPU Per HLD, creating BFD passive sessions on DPU side when HA state is activated. Also removing the passive sessions in planned shutdown. This is only applicable to DPU scope HA. Why I did it BFD sessions need to be created on DPU side proactively. How I verified it Tested on Cisco SSW. BFD sessions can be created as expected.
1 parent 41db95a commit cb29d7f

File tree

7 files changed

+356
-16
lines changed

7 files changed

+356
-16
lines changed

orchagent/bfdorch.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,29 @@ void BfdOrch::handleTsaStateChange(bool tsaState)
703703
}
704704
}
705705

706+
void BfdOrch::createSoftwareBfdSession(const string &key, const vector<swss::FieldValueTuple>& data)
707+
{
708+
m_stateSoftBfdSessionTable->set(createStateDBKey(key), data);
709+
SWSS_LOG_NOTICE("Software BFD session created for %s", key.c_str());
710+
}
711+
712+
void BfdOrch::removeSoftwareBfdSession(const string &key)
713+
{
714+
m_stateSoftBfdSessionTable->del(createStateDBKey(key));
715+
SWSS_LOG_NOTICE("Software BFD session removed for %s", key.c_str());
716+
}
717+
718+
void BfdOrch::removeAllSoftwareBfdSessions()
719+
{
720+
vector<string> keys;
721+
m_stateSoftBfdSessionTable->getKeys(keys);
722+
723+
for (auto key : keys)
724+
{
725+
removeSoftwareBfdSession(key);
726+
}
727+
}
728+
706729
BgpGlobalStateOrch::BgpGlobalStateOrch(DBConnector *db, string tableName):
707730
Orch(db, tableName)
708731
{

orchagent/bfdorch.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ class BfdOrch: public Orch, public Subject
1919
virtual ~BfdOrch(void);
2020
void handleTsaStateChange(bool tsaState);
2121

22+
/* APIs for HaOrch to create passive BFD sessions on DPU.*/
23+
virtual void createSoftwareBfdSession(
24+
const std::string& key,
25+
const std::vector<swss::FieldValueTuple>& data);
26+
virtual void removeSoftwareBfdSession(
27+
const std::string& key);
28+
virtual void removeAllSoftwareBfdSessions();
29+
2230
private:
2331
bool create_bfd_session(const std::string& key, const std::vector<swss::FieldValueTuple>& data);
2432
bool remove_bfd_session(const std::string& key);

orchagent/dash/dashhaorch.cpp

Lines changed: 135 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "orch.h"
44
#include "sai.h"
55
#include "saiextensions.h"
6+
#include "bfdorch.h"
67
#include "dashorch.h"
78
#include "crmorch.h"
89
#include "saihelper.h"
@@ -58,9 +59,10 @@ static const map<sai_ha_scope_event_t, string> sai_ha_scope_event_type_name =
5859
{ SAI_HA_SCOPE_EVENT_SPLIT_BRAIN_DETECTED, "split_brain_detected" }
5960
};
6061

61-
DashHaOrch::DashHaOrch(DBConnector *db, const vector<string> &tables, DashOrch *dash_orch, DBConnector *app_state_db, ZmqServer *zmqServer) :
62+
DashHaOrch::DashHaOrch(DBConnector *db, const vector<string> &tables, DashOrch *dash_orch, BfdOrch *bfd_orch, DBConnector *app_state_db, ZmqServer *zmqServer) :
6263
ZmqOrch(db, tables, zmqServer),
63-
m_dash_orch(dash_orch)
64+
m_dash_orch(dash_orch),
65+
m_bfd_orch(bfd_orch)
6466
{
6567
SWSS_LOG_ENTER();
6668

@@ -524,7 +526,7 @@ bool DashHaOrch::addHaScopeEntry(const std::string &key, const dash::ha_scope::H
524526
return parseHandleSaiStatusFailure(handle_status);
525527
}
526528
}
527-
m_ha_scope_entries[key] = HaScopeEntry {sai_ha_scope_oid, entry, getNowTime()};
529+
m_ha_scope_entries[key] = HaScopeEntry {sai_ha_scope_oid, entry, getNowTime(), SAI_DASH_HA_STATE_DEAD, getNowTime()};
528530
SWSS_LOG_NOTICE("Created HA Scope object for %s", key.c_str());
529531

530532
// set HA Scope ID to ENI
@@ -574,6 +576,18 @@ bool DashHaOrch::setHaScopeHaRole(const std::string &key, const dash::ha_scope::
574576

575577
sai_object_id_t ha_scope_id = m_ha_scope_entries[key].ha_scope_id;
576578

579+
/*
580+
Remove bfd passive sessions in planned shutdown (scope == DPU)
581+
*/
582+
if (entry.ha_role() == dash::types::HA_ROLE_DEAD
583+
&& !m_ha_set_entries.empty())
584+
{
585+
if (has_dpu_scope())
586+
{
587+
m_bfd_orch->removeAllSoftwareBfdSessions();
588+
}
589+
}
590+
577591
sai_attribute_t ha_scope_attr;
578592
ha_scope_attr.id = SAI_HA_SCOPE_ATTR_DASH_HA_ROLE;
579593
ha_scope_attr.value.u32 = to_sai(entry.ha_role());
@@ -806,6 +820,68 @@ void DashHaOrch::doTaskHaScopeTable(ConsumerBase &consumer)
806820
}
807821
}
808822

823+
void DashHaOrch::doTaskBfdSessionTable(ConsumerBase &consumer)
824+
{
825+
SWSS_LOG_ENTER();
826+
827+
auto it = consumer.m_toSync.begin();
828+
while (it != consumer.m_toSync.end())
829+
{
830+
KeyOpFieldsValuesTuple tuple = it->second;
831+
const auto& key = kfvKey(tuple);
832+
const auto& op = kfvOp(tuple);
833+
834+
SWSS_LOG_DEBUG("Processing BFD Session table");
835+
836+
if (op == SET_COMMAND)
837+
{
838+
if (has_eni_scope())
839+
{
840+
m_bfd_orch->createSoftwareBfdSession(key, kfvFieldsValues(tuple));
841+
}
842+
843+
// Per HLD, once the state is moved to Active/Standby/Standalone state, we will create the BFD responder on DPU.
844+
bool has_dpu_scope_ha_state_activated = false;
845+
if (has_dpu_scope())
846+
{
847+
for (const auto& ha_scope_entry : m_ha_scope_entries)
848+
{
849+
if (in(ha_scope_entry.second.ha_state, {SAI_DASH_HA_STATE_ACTIVE,
850+
SAI_DASH_HA_STATE_STANDBY,
851+
SAI_DASH_HA_STATE_STANDALONE}))
852+
{
853+
has_dpu_scope_ha_state_activated = true;
854+
break;
855+
}
856+
}
857+
}
858+
859+
if (has_dpu_scope_ha_state_activated)
860+
{
861+
m_bfd_orch->createSoftwareBfdSession(key, kfvFieldsValues(tuple));
862+
}
863+
864+
/*
865+
Caching BFD sessions for planned ha_role up->down->up.
866+
*/
867+
if ((!has_eni_scope()))
868+
{
869+
SWSS_LOG_INFO("Caching BFD session %s as there is no non-dead DPU HA Scope", key.c_str());
870+
871+
m_bfd_session_pending_creation[key] = kfvFieldsValues(tuple);
872+
}
873+
874+
it = consumer.m_toSync.erase(it);
875+
}
876+
else if (op == DEL_COMMAND)
877+
{
878+
m_bfd_orch->removeSoftwareBfdSession(key);
879+
it = consumer.m_toSync.erase(it);
880+
m_bfd_session_pending_creation.erase(key);
881+
}
882+
}
883+
}
884+
809885
void DashHaOrch::doTask(ConsumerBase &consumer)
810886
{
811887
SWSS_LOG_ENTER();
@@ -817,7 +893,12 @@ void DashHaOrch::doTask(ConsumerBase &consumer)
817893
else if (consumer.getTableName() == APP_DASH_HA_SCOPE_TABLE_NAME)
818894
{
819895
doTaskHaScopeTable(consumer);
820-
} else
896+
}
897+
else if (consumer.getTableName() == APP_BFD_SESSION_TABLE_NAME)
898+
{
899+
doTaskBfdSessionTable(consumer);
900+
}
901+
else
821902
{
822903
SWSS_LOG_ERROR("Unknown table: %s", consumer.getTableName().c_str());
823904
}
@@ -929,6 +1010,17 @@ void DashHaOrch::doTask(NotificationConsumer &consumer)
9291010
}
9301011

9311012
fvs.push_back({"ha_state", sai_ha_state_name.at(ha_scope_event[i].ha_state)});
1013+
fvs.push_back({"ha_state_start_time", to_string(now_time)});
1014+
1015+
m_ha_scope_entries[key].ha_state = ha_scope_event[i].ha_state;
1016+
m_ha_scope_entries[key].last_state_start_time = now_time;
1017+
1018+
if (has_dpu_scope() && in(ha_scope_event[i].ha_state, {SAI_DASH_HA_STATE_ACTIVE,
1019+
SAI_DASH_HA_STATE_STANDBY,
1020+
SAI_DASH_HA_STATE_STANDALONE}))
1021+
{
1022+
processCachedBfdSessions();
1023+
}
9321024
break;
9331025
default:
9341026
SWSS_LOG_ERROR("Unknown HA Scope event type %d for %s", event_type, key.c_str());
@@ -1113,4 +1205,42 @@ bool DashHaOrch::convertKfvToHaScopePb(const std::vector<FieldValueTuple> &kfv,
11131205
}
11141206
}
11151207
return true;
1116-
}
1208+
}
1209+
1210+
bool DashHaOrch::has_dpu_scope()
1211+
{
1212+
for (const auto& ha_set_entry : m_ha_set_entries)
1213+
{
1214+
if (ha_set_entry.second.metadata.scope() == dash::types::HA_SCOPE_DPU)
1215+
{
1216+
return true;
1217+
}
1218+
}
1219+
return false;
1220+
}
1221+
1222+
bool DashHaOrch::has_eni_scope()
1223+
{
1224+
for (const auto& ha_set_entry : m_ha_set_entries)
1225+
{
1226+
if (ha_set_entry.second.metadata.scope() == dash::types::HA_SCOPE_ENI)
1227+
{
1228+
return true;
1229+
}
1230+
}
1231+
return false;
1232+
}
1233+
1234+
void DashHaOrch::processCachedBfdSessions()
1235+
{
1236+
/*
1237+
Create bfd passive sessions cached when moving out of DEAD role (scope == DPU)
1238+
*/
1239+
if (has_dpu_scope() && !m_bfd_session_pending_creation.empty())
1240+
{
1241+
for (const auto& bfd_entry : m_bfd_session_pending_creation)
1242+
{
1243+
m_bfd_orch->createSoftwareBfdSession(bfd_entry.first, bfd_entry.second);
1244+
}
1245+
}
1246+
}

orchagent/dash/dashhaorch.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "dbconnector.h"
66
#include "dashorch.h"
7+
#include "bfdorch.h"
78
#include "zmqorch.h"
89
#include "zmqserver.h"
910
#include "saitypes.h"
@@ -28,10 +29,14 @@ struct HaScopeEntry
2829
sai_object_id_t ha_scope_id;
2930
dash::ha_scope::HaScope metadata;
3031
std::time_t last_role_start_time;
32+
33+
sai_dash_ha_state_t ha_state;
34+
std::time_t last_state_start_time;
3135
};
3236

3337
typedef std::map<std::string, HaSetEntry> HaSetTable;
3438
typedef std::map<std::string, HaScopeEntry> HaScopeTable;
39+
typedef std::map<std::string, vector<swss::FieldValueTuple>> DashBfdSessionTable;
3540

3641
template <typename T>
3742
bool in(T value, std::initializer_list<T> list) {
@@ -41,19 +46,22 @@ bool in(T value, std::initializer_list<T> list) {
4146
class DashHaOrch : public ZmqOrch
4247
{
4348
public:
44-
DashHaOrch(swss::DBConnector *db, const std::vector<std::string> &tableNames, DashOrch *dash_orch, swss::DBConnector *app_state_db, swss::ZmqServer *zmqServer);
49+
DashHaOrch(swss::DBConnector *db, const std::vector<std::string> &tableNames, DashOrch *dash_orch, BfdOrch *bfd_orch, swss::DBConnector *app_state_db, swss::ZmqServer *zmqServer);
4550

4651
protected:
4752
HaSetTable m_ha_set_entries;
4853
HaScopeTable m_ha_scope_entries;
54+
DashBfdSessionTable m_bfd_session_pending_creation;
4955

5056
DashOrch *m_dash_orch;
57+
BfdOrch *m_bfd_orch;
5158

5259
void doTask(ConsumerBase &consumer);
5360
void doTask(swss::NotificationConsumer &consumer);
5461
void doTaskEniTable(ConsumerBase &consumer);
5562
void doTaskHaSetTable(ConsumerBase &consumer);
5663
void doTaskHaScopeTable(ConsumerBase &consumer);
64+
void doTaskBfdSessionTable(ConsumerBase &consumer);
5765

5866
bool addHaSetEntry(const std::string &key, const dash::ha_set::HaSet &entry);
5967
bool removeHaSetEntry(const std::string &key);
@@ -67,6 +75,11 @@ class DashHaOrch : public ZmqOrch
6775
bool register_ha_set_notifier();
6876
bool register_ha_scope_notifier();
6977

78+
bool has_dpu_scope();
79+
bool has_eni_scope();
80+
81+
void processCachedBfdSessions();
82+
7083
bool convertKfvToHaSetPb(
7184
const std::vector<swss::FieldValueTuple> &kfv,
7285
dash::ha_set::HaSet &entry
@@ -96,6 +109,7 @@ class DashHaOrch : public ZmqOrch
96109
public:
97110
const HaSetTable& getHaSetEntries() const { return m_ha_set_entries; };
98111
const HaScopeTable& getHaScopeEntries() const { return m_ha_scope_entries; };
112+
const DashBfdSessionTable& getBfdSessionPendingCreation() const { return m_bfd_session_pending_creation; };
99113
};
100114

101115
#endif // DASHHAORCH_H

orchagent/orchdaemon.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,10 +1280,11 @@ bool DpuOrchDaemon::init()
12801280

12811281
vector<string> dash_ha_tables = {
12821282
APP_DASH_HA_SET_TABLE_NAME,
1283-
APP_DASH_HA_SCOPE_TABLE_NAME
1283+
APP_DASH_HA_SCOPE_TABLE_NAME,
1284+
APP_BFD_SESSION_TABLE_NAME
12841285
};
12851286

1286-
DashHaOrch *dash_ha_orch = new DashHaOrch(m_dpu_appDb, dash_ha_tables, dash_orch, m_dpu_appstateDb, dash_zmq_server);
1287+
DashHaOrch *dash_ha_orch = new DashHaOrch(m_dpu_appDb, dash_ha_tables, dash_orch, gBfdOrch, m_dpu_appstateDb, dash_zmq_server);
12871288
gDirectory.set(dash_ha_orch);
12881289

12891290
vector<string> dash_route_tables = {

0 commit comments

Comments
 (0)