Skip to content

Commit 1636a27

Browse files
committed
Orchestration changes for Error Handling Framework
- Receives notifications from syncd - Process the notifications from syncd and logs the errors into error database - Notify the status to registered applications
1 parent 731a8f5 commit 1636a27

10 files changed

Lines changed: 258 additions & 6 deletions

File tree

orchagent/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ orchagent_SOURCES = \
5353
flexcounterorch.cpp \
5454
watermarkorch.cpp \
5555
policerorch.cpp \
56-
chassisorch.cpp
56+
chassisorch.cpp \
57+
errororch.cpp
5758

5859
orchagent_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
5960
orchagent_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)

orchagent/main.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,11 @@ int main(int argc, char **argv)
294294
DBConnector appl_db(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
295295
DBConnector config_db(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
296296
DBConnector state_db(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
297+
DBConnector counters_db(COUNTERS_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
298+
DBConnector asic_db(ASIC_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
299+
DBConnector error_db(ERROR_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
297300

298-
auto orchDaemon = make_shared<OrchDaemon>(&appl_db, &config_db, &state_db);
301+
auto orchDaemon = make_shared<OrchDaemon>(&appl_db, &config_db, &state_db, &counters_db, &asic_db, &error_db);
299302

300303
if (!orchDaemon->init())
301304
{

orchagent/neighorch.cpp

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
#include "swssnet.h"
55
#include "crmorch.h"
66
#include "routeorch.h"
7+
#include "errororch.h"
8+
#include "tokenize.h"
9+
#include "sai_serialize.h"
10+
#include "redisclient.h"
11+
12+
#include "swss/json.hpp"
13+
using json = nlohmann::json;
714

815
extern sai_neighbor_api_t* sai_neighbor_api;
916
extern sai_next_hop_api_t* sai_next_hop_api;
@@ -12,13 +19,22 @@ extern PortsOrch *gPortsOrch;
1219
extern sai_object_id_t gSwitchId;
1320
extern CrmOrch *gCrmOrch;
1421
extern RouteOrch *gRouteOrch;
22+
extern ErrorOrch *gErrorOrch;
23+
extern std::shared_ptr<swss::RedisClient> g_redisClientAsicDb;
24+
extern std::shared_ptr<swss::RedisClient> g_redisClientCountersDb;
1525

1626
const int neighorch_pri = 30;
1727

1828
NeighOrch::NeighOrch(DBConnector *db, string tableName, IntfsOrch *intfsOrch) :
1929
Orch(db, tableName, neighorch_pri), m_intfsOrch(intfsOrch)
2030
{
2131
SWSS_LOG_ENTER();
32+
33+
if(gErrorOrch->mappingHandlerRegister(APP_NEIGH_TABLE_NAME, this) == false)
34+
{
35+
SWSS_LOG_ERROR("Failed to register with Error Handling Framework for %s",
36+
APP_NEIGH_TABLE_NAME);
37+
}
2238
}
2339

2440
bool NeighOrch::hasNextHop(const NextHopKey &nexthop)
@@ -581,3 +597,129 @@ bool NeighOrch::removeNeighbor(const NeighborEntry &neighborEntry)
581597

582598
return true;
583599
}
600+
601+
bool NeighOrch::mapToErrorDbFormat(sai_object_type_t& object_type, std::vector<FieldValueTuple> &asicValues,
602+
std::vector<FieldValueTuple> &appValues)
603+
{
604+
SWSS_LOG_ENTER();
605+
606+
if(object_type != SAI_OBJECT_TYPE_NEIGHBOR_ENTRY)
607+
{
608+
return false;
609+
}
610+
611+
/*
612+
127.0.0.1:6379> hgetall "NEIGH_TABLE:Ethernet0:2.2.2.2"
613+
1) "neigh"
614+
2) "00:00:3a:3e:9e:a7"
615+
3) "family"
616+
4) "IPv4"
617+
618+
127.0.0.1:6379[1]> hgetall "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY:{\"ip\":\"2.2.2.2\",\"rif\":\"oid:0x60000000006f3\",\"switch_id\":\"oid:0x21000000000000\"}"
619+
1) "SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS"
620+
2) "00:00:3A:3E:9E:A7"
621+
127.0.0.1:6379[1]>
622+
623+
127.0.0.1:6379[2]> hgetall "COUNTERS_PORT_NAME_MAP"
624+
25) "Ethernet0"
625+
26) "oid:0x100000000000e"
626+
*/
627+
628+
const auto& values = asicValues;
629+
std::string asicKV, strNbrIP, strRifOid, strMac;
630+
std::string strIntfName, strRtrIntfType;
631+
for (size_t i = 0; i < values.size(); i++)
632+
{
633+
if(fvField(values[i]) == "key")
634+
{
635+
/* Extract Neighbor IP and Router Interface ID from the "key" field */
636+
asicKV = fvValue(values[i]);
637+
auto tokens = tokenize(asicKV, ':', 1);
638+
json j = json::parse(tokens[1]);
639+
strNbrIP = j["ip"];
640+
strRifOid = j["rif"];
641+
SWSS_LOG_DEBUG("Neighbor IP is %s, router interface ID is %s",
642+
strNbrIP.c_str(), strRifOid.c_str());
643+
644+
/* Extract Port OID from Router Interface OID */
645+
std::string strRtrIfKey = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:" + strRifOid;
646+
std::string strIntfOid;
647+
/* OID in neighbor entry points to ROUTER_INTERFACE
648+
* Port based routing interface
649+
* ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000006d9
650+
* SAI_ROUTER_INTERFACE_ATTR_TYPE = SAI_ROUTER_INTERFACE_TYPE_PORT
651+
* SAI_ROUTER_INTERFACE_ATTR_PORT_ID = oid:0x100000000000e
652+
* Check above oid in COUNTERS_PORT_NAME_MAP in COUNTERS_DB to get the physical interface name
653+
*
654+
* VLAN based routing interface
655+
* ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000006f6
656+
* SAI_ROUTER_INTERFACE_ATTR_TYPE -> SAI_ROUTER_INTERFACE_TYPE_VLAN
657+
* SAI_ROUTER_INTERFACE_ATTR_VLAN_ID -> oid:0x260000000006f3
658+
* Check above oid in "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:oid:0x260000000006f3"
659+
*/
660+
661+
auto hashRif = g_redisClientAsicDb->hgetall(strRtrIfKey);
662+
for (auto &kv: hashRif)
663+
{
664+
const std::string &skey = kv.first;
665+
const std::string &svalue = kv.second;
666+
667+
if(skey == "SAI_ROUTER_INTERFACE_ATTR_TYPE")
668+
{
669+
strRtrIntfType = svalue;
670+
}
671+
if(skey == "SAI_ROUTER_INTERFACE_ATTR_PORT_ID" || skey == "SAI_ROUTER_INTERFACE_ATTR_VLAN_ID")
672+
{
673+
strIntfOid = svalue;
674+
}
675+
}
676+
SWSS_LOG_DEBUG("Router interface type is %s, interface ID is %s",
677+
strRtrIntfType.c_str(), strIntfOid.c_str());
678+
679+
/* Extract Port name from the Port OID */
680+
if(strRtrIntfType == "SAI_ROUTER_INTERFACE_TYPE_PORT")
681+
{
682+
auto hashCntr = g_redisClientCountersDb->hgetall("COUNTERS_PORT_NAME_MAP");
683+
for (auto &kv: hashCntr)
684+
{
685+
const std::string &skey = kv.first;
686+
const std::string &svalue = kv.second;
687+
if(svalue == strIntfOid)
688+
{
689+
strIntfName = skey;
690+
break;
691+
}
692+
}
693+
}
694+
else if (strRtrIntfType == "SAI_ROUTER_INTERFACE_TYPE_VLAN")
695+
{
696+
std::string strVlanKey = "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:" + strIntfOid;
697+
auto hashVlan = g_redisClientAsicDb->hgetall(strVlanKey);
698+
for (auto &kv: hashVlan)
699+
{
700+
const std::string &skey = kv.first;
701+
const std::string &svalue = kv.second;
702+
if(skey == "SAI_VLAN_ATTR_VLAN_ID")
703+
{
704+
strIntfName = "Vlan" + svalue;
705+
break;
706+
}
707+
}
708+
}
709+
SWSS_LOG_DEBUG("Interface name is %s", strIntfName.c_str());
710+
} /* End of if(fvField(values[i]) == "key") */
711+
712+
/* Extract MAC address */
713+
if(fvField(values[i]) == "SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS")
714+
{
715+
strMac = fvValue(values[i]);
716+
}
717+
} /* End of for (size_t i = 0; i < values.size(); i++) */
718+
719+
std::string appKey = strIntfName + ":" + strNbrIP;
720+
appValues.emplace_back("key", appKey);
721+
appValues.emplace_back("neigh", strMac);
722+
723+
return true;
724+
}
725+

orchagent/neighorch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class NeighOrch : public Orch, public Subject
6767
bool clearNextHopFlag(const NextHopKey &, const uint32_t);
6868

6969
void doTask(Consumer &consumer);
70+
bool mapToErrorDbFormat(sai_object_type_t& object_type, std::vector<FieldValueTuple> &asicValues,
71+
std::vector<FieldValueTuple> &appValues);
7072
};
7173

7274
#endif /* SWSS_NEIGHORCH_H */

orchagent/orch.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,12 @@ string Orch::dumpTuple(Consumer &consumer, KeyOpFieldsValuesTuple &tuple)
432432
return s;
433433
}
434434

435+
bool Orch::mapToErrorDbFormat(sai_object_type_t& object_type, std::vector<FieldValueTuple> &asicValues,
436+
std::vector<FieldValueTuple> &appValues)
437+
{
438+
return false;
439+
}
440+
435441
ref_resolve_status Orch::resolveFieldRefArray(
436442
type_map &type_maps,
437443
const string &field_name,

orchagent/orch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ class Orch
195195
static void recordTuple(Consumer &consumer, swss::KeyOpFieldsValuesTuple &tuple);
196196

197197
void dumpPendingTasks(std::vector<std::string> &ts);
198+
virtual bool mapToErrorDbFormat(sai_object_type_t& object_type, std::vector<FieldValueTuple> &asicValues,
199+
std::vector<FieldValueTuple> &appValues);
198200
protected:
199201
ConsumerMap m_consumerMap;
200202

orchagent/orchdaemon.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,25 @@ AclOrch *gAclOrch;
3333
CrmOrch *gCrmOrch;
3434
BufferOrch *gBufferOrch;
3535
SwitchOrch *gSwitchOrch;
36+
ErrorOrch *gErrorOrch;
3637
Directory<Orch*> gDirectory;
3738

38-
OrchDaemon::OrchDaemon(DBConnector *applDb, DBConnector *configDb, DBConnector *stateDb) :
39+
std::shared_ptr<swss::RedisClient> g_redisClientAppDb;
40+
std::shared_ptr<swss::RedisClient> g_redisClientAsicDb;
41+
std::shared_ptr<swss::RedisClient> g_redisClientCountersDb;
42+
43+
OrchDaemon::OrchDaemon(DBConnector *applDb, DBConnector *configDb, DBConnector *stateDb, DBConnector *countersDb, DBConnector *asicDb, DBConnector *errorDb) :
3944
m_applDb(applDb),
4045
m_configDb(configDb),
41-
m_stateDb(stateDb)
46+
m_stateDb(stateDb),
47+
m_countersDb(countersDb),
48+
m_asicDb(asicDb),
49+
m_errorDb(errorDb)
4250
{
4351
SWSS_LOG_ENTER();
52+
g_redisClientAppDb = std::make_shared<swss::RedisClient>(applDb);
53+
g_redisClientAsicDb = std::make_shared<swss::RedisClient>(asicDb);
54+
g_redisClientCountersDb = std::make_shared<swss::RedisClient>(countersDb);
4455
}
4556

4657
OrchDaemon::~OrchDaemon()
@@ -68,6 +79,11 @@ bool OrchDaemon::init()
6879

6980
string platform = getenv("platform") ? getenv("platform") : "";
7081

82+
vector<string> error_tables = {
83+
{ ERROR_ROUTE_TABLE_NAME},
84+
{ ERROR_NEIGH_TABLE_NAME}
85+
};
86+
gErrorOrch = new ErrorOrch(m_asicDb, m_errorDb, error_tables);
7187
gSwitchOrch = new SwitchOrch(m_applDb, APP_SWITCH_TABLE_NAME);
7288

7389
const int portsorch_base_pri = 40;
@@ -193,7 +209,7 @@ bool OrchDaemon::init()
193209
* when iterating ConsumerMap.
194210
* That is ensured implicitly by the order of map key, "LAG_TABLE" is smaller than "VLAN_TABLE" in lexicographic order.
195211
*/
196-
m_orchList = { gSwitchOrch, gCrmOrch, gBufferOrch, gPortsOrch, gIntfsOrch, gNeighOrch, gRouteOrch, copp_orch, tunnel_decap_orch, qos_orch, wm_orch, policer_orch };
212+
m_orchList = { gErrorOrch, gSwitchOrch, gCrmOrch, gBufferOrch, gPortsOrch, gIntfsOrch, gNeighOrch, gRouteOrch, copp_orch, tunnel_decap_orch, qos_orch, wm_orch, policer_orch };
197213

198214

199215
bool initialize_dtel = false;

orchagent/orchdaemon.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "vrforch.h"
2424
#include "vxlanorch.h"
2525
#include "vnetorch.h"
26+
#include "errororch.h"
2627
#include "countercheckorch.h"
2728
#include "flexcounterorch.h"
2829
#include "watermarkorch.h"
@@ -34,7 +35,7 @@ using namespace swss;
3435
class OrchDaemon
3536
{
3637
public:
37-
OrchDaemon(DBConnector *, DBConnector *, DBConnector *);
38+
OrchDaemon(DBConnector *, DBConnector *, DBConnector *, DBConnector *, DBConnector *, DBConnector *);
3839
~OrchDaemon();
3940

4041
bool init();
@@ -48,6 +49,9 @@ class OrchDaemon
4849
DBConnector *m_applDb;
4950
DBConnector *m_configDb;
5051
DBConnector *m_stateDb;
52+
DBConnector *m_countersDb;
53+
DBConnector *m_asicDb;
54+
DBConnector *m_errorDb;
5155

5256
std::vector<Orch *> m_orchList;
5357
Select *m_select;

orchagent/routeorch.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
#include "logger.h"
55
#include "swssnet.h"
66
#include "crmorch.h"
7+
#include "tokenize.h"
8+
#include "errororch.h"
9+
#include "sai_serialize.h"
10+
#include "redisclient.h"
11+
12+
#include "swss/json.hpp"
13+
using json = nlohmann::json;
14+
using namespace swss;
715

816
extern sai_object_id_t gVirtualRouterId;
917
extern sai_object_id_t gSwitchId;
@@ -15,6 +23,10 @@ extern sai_switch_api_t* sai_switch_api;
1523
extern PortsOrch *gPortsOrch;
1624
extern IntfsOrch *gIntfsOrch;
1725
extern CrmOrch *gCrmOrch;
26+
extern ErrorOrch *gErrorOrch;
27+
extern std::shared_ptr<swss::RedisClient> g_redisClientAppDb;
28+
extern std::shared_ptr<swss::RedisClient> g_redisClientAsicDb;
29+
extern std::shared_ptr<swss::RedisClient> g_redisClientCountersDb;
1830

1931
/* Default maximum number of next hop groups */
2032
#define DEFAULT_NUMBER_OF_ECMP_GROUPS 128
@@ -30,6 +42,12 @@ RouteOrch::RouteOrch(DBConnector *db, string tableName, NeighOrch *neighOrch) :
3042
{
3143
SWSS_LOG_ENTER();
3244

45+
if(gErrorOrch->mappingHandlerRegister(APP_ROUTE_TABLE_NAME, this) == false)
46+
{
47+
SWSS_LOG_ERROR("Failed to register with Error Handling Framework for %s",
48+
APP_ROUTE_TABLE_NAME);
49+
}
50+
3351
sai_attribute_t attr;
3452
attr.id = SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS;
3553

@@ -1097,3 +1115,59 @@ bool RouteOrch::removeRoute(const IpPrefix &ipPrefix)
10971115

10981116
return true;
10991117
}
1118+
1119+
bool RouteOrch::mapToErrorDbFormat(sai_object_type_t& object_type, std::vector<FieldValueTuple> &asicValues,
1120+
std::vector<FieldValueTuple> &appValues)
1121+
{
1122+
SWSS_LOG_ENTER();
1123+
1124+
if(object_type != SAI_OBJECT_TYPE_ROUTE_ENTRY)
1125+
{
1126+
return false;
1127+
}
1128+
1129+
/*
1130+
127.0.0.1:6379> hgetall "ROUTE_TABLE:1.1.1.0/24"
1131+
1) "nexthop"
1132+
2) "2.2.2.2"
1133+
3) "ifname"
1134+
4) "Ethernet0"
1135+
1136+
127.0.0.1:6379[1]> hgetall "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"1.1.1.0/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000028\"}"
1137+
1) "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"
1138+
2) "oid:0x40000000006fd"
1139+
127.0.0.1:6379[1]>
1140+
1141+
*/
1142+
1143+
const auto& values = asicValues;
1144+
std::string asicKV, strNhopKey, strNextHopIP;
1145+
std::string strRifOid, strPrefix, strIntfName, strRtrIntfType;
1146+
for (size_t i = 0; i < values.size(); i++)
1147+
{
1148+
/* Extract IP prefix from the key */
1149+
if(fvField(values[i]) == "key")
1150+
{
1151+
asicKV = fvValue(values[i]);
1152+
auto tokens = tokenize(asicKV, ':', 1);
1153+
json j = json::parse(tokens[1]);
1154+
strPrefix = j["dest"];
1155+
SWSS_LOG_DEBUG("Prefix is %s", strPrefix.c_str());
1156+
break;
1157+
}
1158+
} /* End of for (i < values.size(); i++) */
1159+
1160+
appValues.emplace_back("key", strPrefix);
1161+
string strRouteTable = APP_ROUTE_TABLE_NAME;
1162+
string strAppKey = strRouteTable + ":" + strPrefix;
1163+
auto hashApp = g_redisClientAppDb->hgetall(strAppKey);
1164+
for (auto &kv: hashApp)
1165+
{
1166+
const std::string &skey = kv.first;
1167+
const std::string &svalue = kv.second;
1168+
appValues.emplace_back(skey, svalue);
1169+
}
1170+
1171+
return true;
1172+
}
1173+

0 commit comments

Comments
 (0)