-
Notifications
You must be signed in to change notification settings - Fork 0
LAB5 - swss work for lab #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| #include "txerrorcheckorch.h" | ||
| #include "select.h" | ||
| #include "notifier.h" | ||
| #include "sai_serialize.h" | ||
| #include "portsorch.h" | ||
| #include <inttypes.h> | ||
|
|
||
| extern sai_port_api_t *sai_port_api; | ||
| extern PortsOrch *gPortsOrch; | ||
|
|
||
| #define TX_ERROR_CHECK_KEY "TX_ERROR_CHECK" | ||
| #define TX_ERROR_CHECK_POLL_NAME "TX_ERROR_CHECK_POLL" | ||
| #define THRESHOLD_FIELD "threshold" | ||
| #define TIME_PERIOD_FIELD "time_period" | ||
|
|
||
| #define TX_ERROR_PORT_STATE_FIELD "tx_error_port_state" | ||
| #define TX_ERROR_PORT_STATE_ERROR "error" | ||
| #define TX_ERROR_PORT_STATE_OK "ok" | ||
|
|
||
| TxErrorCheckOrch::TxErrorCheckOrch(swss::DBConnector *db, const std::string &tableName): | ||
| Orch(db, tableName) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| m_countersDb = make_shared<swss::DBConnector>("COUNTERS_DB", 0); | ||
| m_countersTable = make_unique<swss::Table>(m_countersDb.get(), COUNTERS_TABLE); | ||
| m_configDb = make_unique<swss::DBConnector>("CONFIG_DB", 0); | ||
| m_stateDb = make_unique<swss::DBConnector>("STATE_DB", 0); | ||
|
|
||
| auto interv = timespec { .tv_sec = TX_ERROR_CHECK_POLL_TIMEOUT_SEC_DEFAULT, .tv_nsec = 0 }; | ||
| m_timer = std::make_shared<swss::SelectableTimer>(interv); | ||
| auto executor = new ExecutableTimer(m_timer.get(), this, TX_ERROR_CHECK_POLL_NAME); | ||
| Orch::addExecutor(executor); | ||
| m_timer->start(); | ||
| } | ||
|
|
||
| TxErrorCheckOrch::~TxErrorCheckOrch(void) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
| } | ||
|
|
||
| void TxErrorCheckOrch::doTask(swss::SelectableTimer &timer) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| mcCounterCheck(); | ||
| } | ||
|
|
||
| void TxErrorCheckOrch::doTask(Consumer &consumer) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| if (consumer.getTableName() != CFG_TX_ERROR_CHECK_TABLE_NAME) | ||
| { | ||
| SWSS_LOG_ERROR("Unknown table name %s", consumer.getTableName().c_str()); | ||
| return; | ||
| } | ||
|
|
||
| auto it = consumer.m_toSync.begin(); | ||
| while (it != consumer.m_toSync.end()) | ||
| { | ||
| mcFieldsUpdate(it->second); | ||
| it = consumer.m_toSync.erase(it); | ||
| } | ||
| } | ||
|
|
||
| void TxErrorCheckOrch::mcCounterCheck() | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| for (auto const &port : gPortsOrch->getAllPorts()) | ||
| { | ||
| sai_object_id_t portOid = port.second.m_port_id; | ||
| if (portOid == SAI_NULL_OBJECT_ID) | ||
| { | ||
| SWSS_LOG_ERROR("Invalid port oid %lx" PRIx64, port.second.m_port_id); | ||
| continue; | ||
| } | ||
|
|
||
| std::string outErrors; | ||
|
|
||
| if (!m_countersTable->hget(sai_serialize_object_id(portOid), "SAI_PORT_STAT_IF_OUT_ERRORS", outErrors)) | ||
| { | ||
| SWSS_LOG_ERROR("Access to Counters DB with %lx port ID failed", port.second.m_port_id); | ||
| continue; | ||
| } | ||
|
|
||
| uint32_t outErrorsCount = to_uint<uint32_t>(outErrors); | ||
|
|
||
| /* Note: for now the support is only for error state true; if needed we can add support for error state false. */ | ||
| if (outErrorsCount > m_error_threshold) | ||
| { | ||
| setPortStatus(port.second.m_alias, true); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void TxErrorCheckOrch::mcFieldsUpdate(swss::KeyOpFieldsValuesTuple keyOpFieldsValues) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| string key = kfvKey(keyOpFieldsValues); | ||
|
|
||
| if (key != TX_ERROR_CHECK_KEY) | ||
| { | ||
| SWSS_LOG_ERROR("Unknown key %s", key.c_str()); | ||
| return; | ||
| } | ||
|
|
||
| auto op = kfvOp(keyOpFieldsValues); | ||
| if ((op != DEL_COMMAND) && (op != SET_COMMAND)) | ||
| { | ||
| SWSS_LOG_ERROR("Unknown operation %s", op.c_str()); | ||
| return; | ||
| } | ||
|
|
||
| for (auto fvMap : kfvFieldsValues(keyOpFieldsValues)) | ||
| { | ||
| auto fieldName = fvField(fvMap); | ||
| auto fieldValue = fvValue(fvMap); | ||
|
|
||
| if (fieldName == THRESHOLD_FIELD) | ||
| { | ||
| if (op == DEL_COMMAND) | ||
| { | ||
| fieldValue = std::to_string(TX_ERROR_CHECK_THRESHOLD_DEFAULT); | ||
| } | ||
|
|
||
| mcUpdateThreshold(to_uint<uint64_t>(fieldValue)); | ||
| } | ||
| else if (fieldName == TIME_PERIOD_FIELD) | ||
| { | ||
| if (op == DEL_COMMAND) | ||
| { | ||
| fieldValue = std::to_string(TX_ERROR_CHECK_POLL_TIMEOUT_SEC_DEFAULT); | ||
| } | ||
|
|
||
| mcUpdateTimePeriod(to_uint<time_t>(fieldValue)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void TxErrorCheckOrch::mcUpdateThreshold(uint64_t new_threshold) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| m_error_threshold = new_threshold; | ||
| } | ||
|
|
||
| void TxErrorCheckOrch::mcUpdateTimePeriod(time_t new_time_period) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| auto new_interv = timespec { .tv_sec = new_time_period, .tv_nsec = 0 }; | ||
| m_timer->setInterval(new_interv); | ||
| m_timer->reset(); | ||
| } | ||
|
|
||
| void TxErrorCheckOrch::setPortStatus(std::string port_name, bool isTxErrorState) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| swss::Table portStateTable(m_stateDb.get(), STATE_PORT_TABLE_NAME); | ||
| portStateTable.hset(port_name, TX_ERROR_PORT_STATE_FIELD, (isTxErrorState ? TX_ERROR_PORT_STATE_ERROR : TX_ERROR_PORT_STATE_OK)); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #pragma once | ||
|
|
||
| #include <array> | ||
| #include <linux/timer.h> | ||
| #include "orch.h" | ||
| #include "dbconnector.h" | ||
| #include "table.h" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @abelamit double quotes for a local includes, and angle brackets for an external libraries The best practices:
That helps to improve code readability
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
|
|
||
| extern "C" { | ||
| #include "sai.h" | ||
| } | ||
|
|
||
| #define TX_ERROR_CHECK_THRESHOLD_DEFAULT 1 | ||
| #define TX_ERROR_CHECK_POLL_TIMEOUT_SEC_DEFAULT 5 | ||
|
|
||
| class TxErrorCheckOrch: public Orch | ||
| { | ||
| public: | ||
| TxErrorCheckOrch(swss::DBConnector *db, const std::string &tableName); | ||
| virtual ~TxErrorCheckOrch(void); | ||
| void doTask(swss::SelectableTimer &timer); | ||
| void doTask(Consumer &consumer); | ||
|
|
||
| private: | ||
| void mcCounterCheck(); | ||
| void mcFieldsUpdate(swss::KeyOpFieldsValuesTuple keyOpFieldsValues); | ||
| void mcUpdateThreshold(uint64_t new_threshold); | ||
| void mcUpdateTimePeriod(time_t new_time_period); | ||
| void setPortStatus(std::string port_name, bool isTxErrorState); | ||
|
|
||
| std::shared_ptr<swss::DBConnector> m_countersDb = nullptr; | ||
| std::unique_ptr<swss::Table> m_countersTable = nullptr; | ||
| std::unique_ptr<swss::DBConnector> m_configDb = nullptr; | ||
| std::unique_ptr<swss::DBConnector> m_stateDb = nullptr; | ||
|
|
||
| uint64_t m_error_threshold = TX_ERROR_CHECK_THRESHOLD_DEFAULT; | ||
| std::shared_ptr<swss::SelectableTimer> m_timer = nullptr; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import time | ||
| import pytest | ||
|
|
||
| from swsscommon import swsscommon | ||
|
|
||
| TX_ERROR_CHECK_POLL_TIMEOUT_SEC_DEFAULT = (5 * 60) | ||
| TX_ERROR_CHECK_THRESHOLD_DEFAULT = (5 * 60) | ||
|
|
||
| CFG_TX_ERROR_CHECK_TABLE_NAME = "CFG_TX_ERROR_CHECK" | ||
| TX_ERROR_CHECK_KEY = "TX_ERROR_CHECK" | ||
| TX_ERROR_CHECK_POLL_NAME = "TX_ERROR_CHECK_POLL" | ||
| THRESHOLD_FIELD = "threshold" | ||
| TIME_PERIOD_FIELD = "time_period" | ||
|
|
||
| TX_ERROR_PORT_STATE_FIELD = "tx_error_port_state" | ||
| TX_ERROR_PORT_STATE_ERROR = "error" | ||
| TX_ERROR_PORT_STATE_OK = "ok" | ||
|
|
||
| # port to be tested | ||
| PORT = "Ethernet0" | ||
|
|
||
| @pytest.mark.usefixtures('dvs_port_manager') | ||
| class TestTxErrorCounters(object): | ||
| def setup_db(self, dvs): | ||
| self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0) | ||
| self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0) | ||
| self.flex_db = swsscommon.DBConnector(5, dvs.redis_sock, 0) | ||
| self.state_db = swsscommon.DBConnector(6, dvs.redis_sock, 0) | ||
| self.counters_db = swsscommon.DBConnector(2, dvs.redis_sock, 0) | ||
|
|
||
| def genericGetAndAssert(self, table, key): | ||
| status, fields = table.get(key) | ||
| assert status | ||
| return fields | ||
|
|
||
| def set_tx_error_config(self, field, value): | ||
| tx_error_table = swsscommon.Table(self.config_db, CFG_TX_ERROR_CHECK_TABLE_NAME) | ||
| entry = swsscommon.FieldValuePairs([(field, value)]) | ||
| tx_error_table.set(TX_ERROR_CHECK_KEY, entry) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@abelamit FYI. Usually we do no do like this, only in a very rare cases. Different vendors may want to have different defaults
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand. So how will you define default values? Since we need to upload our system with some default before user is configuring. Basically it is not mandatory to support this in DB_CONFIG