diff --git a/common/database_config.json b/common/database_config.json index 1750ca758..e32dae81f 100644 --- a/common/database_config.json +++ b/common/database_config.json @@ -64,17 +64,17 @@ }, "GB_ASIC_DB" : { "id" : 9, - "separator": "|", + "separator": ":", "instance" : "redis" }, "GB_COUNTERS_DB" : { "id" : 10, - "separator": "|", + "separator": ":", "instance" : "redis" }, "GB_FLEX_COUNTER_DB" : { "id" : 11, - "separator": "|", + "separator": ":", "instance" : "redis" }, "CHASSIS_APP_DB" : { diff --git a/common/rediscommand.cpp b/common/rediscommand.cpp index 9d362959d..51fe98b9e 100644 --- a/common/rediscommand.cpp +++ b/common/rediscommand.cpp @@ -88,6 +88,18 @@ void RedisCommand::formatHDEL(const std::string& key, const std::vector(args.size()), args.data(), NULL); } +/* Format EXPIRE key field command */ +void RedisCommand::formatEXPIRE(const std::string& key, const int64_t& ttl) +{ + return format("EXPIRE %s %lld", key.c_str(), ttl); +} + +/* Format TTL key command */ +void RedisCommand::formatTTL(const std::string& key) +{ + return format("TTL %s", key.c_str()); +} + const char *RedisCommand::c_str() const { return temp; diff --git a/common/rediscommand.h b/common/rediscommand.h index 46f214f6e..fb96f4584 100644 --- a/common/rediscommand.h +++ b/common/rediscommand.h @@ -50,6 +50,12 @@ class RedisCommand { /* Format HDEL key multiple fields command */ void formatHDEL(const std::string& key, const std::vector& fields); + /* Format EXPIRE key ttl command */ + void formatEXPIRE(const std::string& key, const int64_t& ttl); + + /* Format TTL key command */ + void formatTTL(const std::string& key); + const char *c_str() const; size_t length() const; diff --git a/common/schema.h b/common/schema.h index 21a6bb156..454c8a2c4 100644 --- a/common/schema.h +++ b/common/schema.h @@ -41,6 +41,7 @@ namespace swss { #define APP_PFC_WD_TABLE_NAME "PFC_WD_TABLE" #define APP_SWITCH_TABLE_NAME "SWITCH_TABLE" #define APP_NEXTHOP_GROUP_TABLE_NAME "NEXTHOP_GROUP_TABLE" +#define APP_CLASS_BASED_NEXT_HOP_GROUP_TABLE_NAME "CLASS_BASED_NEXT_HOP_GROUP_TABLE" #define APP_COPP_TABLE_NAME "COPP_TABLE" #define APP_VRF_TABLE_NAME "VRF_TABLE" @@ -80,6 +81,8 @@ namespace swss { #define APP_ISOLATION_GROUP_TABLE_NAME "ISOLATION_GROUP_TABLE" #define APP_BFD_SESSION_TABLE_NAME "BFD_SESSION_TABLE" +#define APP_FC_TO_NHG_INDEX_MAP_TABLE_NAME "FC_TO_NHG_INDEX_MAP_TABLE" + /***** ASIC DATABASE *****/ #define ASIC_TEMPERATURE_INFO_TABLE_NAME "ASIC_TEMPERATURE_INFO" @@ -131,6 +134,7 @@ namespace swss { #define COUNTERS_PG_INDEX_MAP "COUNTERS_PG_INDEX_MAP" #define COUNTERS_RIF_TYPE_MAP "COUNTERS_RIF_TYPE_MAP" #define COUNTERS_RIF_NAME_MAP "COUNTERS_RIF_NAME_MAP" +#define COUNTERS_TRAP_NAME_MAP "COUNTERS_TRAP_NAME_MAP" #define COUNTERS_CRM_TABLE "CRM" #define COUNTERS_BUFFER_POOL_NAME_MAP "COUNTERS_BUFFER_POOL_NAME_MAP" #define COUNTERS_SWITCH_NAME_MAP "COUNTERS_SWITCH_NAME_MAP" @@ -179,6 +183,7 @@ namespace swss { #define MACSEC_SA_ATTR_ID_LIST "MACSEC_SA_ATTR_ID_LIST" #define TUNNEL_ATTR_ID_LIST "TUNNEL_ATTR_ID_LIST" #define ACL_COUNTER_ATTR_ID_LIST "ACL_COUNTER_ATTR_ID_LIST" +#define FLOW_COUNTER_ID_LIST "FLOW_COUNTER_ID_LIST" #define PLUGIN_TABLE "PLUGIN_TABLE" #define LUA_PLUGIN_TYPE "LUA_PLUGIN_TYPE" #define SAI_OBJECT_TYPE "SAI_OBJECT_TYPE" @@ -193,6 +198,7 @@ namespace swss { #define PG_PLUGIN_FIELD "PG_PLUGIN_LIST" #define TUNNEL_PLUGIN_FIELD "TUNNEL_PLUGIN_LIST" #define BUFFER_POOL_PLUGIN_FIELD "BUFFER_POOL_PLUGIN_LIST" +#define FLOW_COUNTER_PLUGIN_FIELD "FLOW_COUNTER_PLUGIN_FIELD" #define FLEX_COUNTER_STATUS_FIELD "FLEX_COUNTER_STATUS" #define FLEX_COUNTER_GROUP_TABLE "FLEX_COUNTER_GROUP_TABLE" #define FLEX_COUNTER_DELAY_STATUS_FIELD "FLEX_COUNTER_DELAY_STATUS" @@ -259,6 +265,8 @@ namespace swss { #define CFG_WRED_PROFILE_TABLE_NAME "WRED_PROFILE" #define CFG_QUEUE_TABLE_NAME "QUEUE" #define CFG_DOT1P_TO_TC_MAP_TABLE_NAME "DOT1P_TO_TC_MAP" +#define CFG_DSCP_TO_FC_MAP_TABLE_NAME "DSCP_TO_FC_MAP" +#define CFG_EXP_TO_FC_MAP_TABLE_NAME "EXP_TO_FC_MAP" #define CFG_BUFFER_POOL_TABLE_NAME "BUFFER_POOL" #define CFG_BUFFER_PROFILE_TABLE_NAME "BUFFER_PROFILE" diff --git a/common/table.cpp b/common/table.cpp index 5eb4c7d8b..47f5345a9 100644 --- a/common/table.cpp +++ b/common/table.cpp @@ -123,21 +123,56 @@ void Table::hset(const string &key, const std::string &field, const std::string } void Table::set(const string &key, const vector &values, - const string& /*op*/, const string& /*prefix*/) + const string &op, const string &prefix) +{ + set(key, values, op, prefix, DEFAULT_DB_TTL); +} + +// TODO: Implement this without overloading(add an additional ttl param +// to existing set() command once sonic-swss's mock_table.cpp and other +// dependencies can be updated to use the extended new default set()) +void Table::set(const string &key, const vector &values, + const string &op, const string &prefix, const int64_t &ttl) { if (values.size() == 0) return; RedisCommand cmd; + cmd.formatHMSET(getKeyName(key), values.begin(), values.end()); - m_pipe->push(cmd, REDIS_REPLY_STATUS); + + if (ttl != DEFAULT_DB_TTL) + { + // Configure the expire time for the entry that was just added + cmd.formatEXPIRE(getKeyName(key), ttl); + m_pipe->push(cmd, REDIS_REPLY_INTEGER); + } + if (!m_buffered) { m_pipe->flush(); } } +bool Table::ttl(const string &key, int64_t &reply_value) +{ + RedisCommand cmd_ttl; + cmd_ttl.formatTTL(getKeyName(key)); + RedisReply r = m_pipe->push(cmd_ttl); + redisReply *reply = r.getContext(); + + if (reply != NULL) + { + reply_value = reply->integer; + return true; + } + else + { + return false; + } +} + void Table::del(const string &key, const string& /* op */, const string& /*prefix*/) { RedisCommand del_key; diff --git a/common/table.h b/common/table.h index 577f8c3b5..6dcc12000 100644 --- a/common/table.h +++ b/common/table.h @@ -164,6 +164,9 @@ class TableEntryEnumerable { void getContent(std::vector &tuples); }; +/* The default time to live for a DB entry is infinite */ +static constexpr int64_t DEFAULT_DB_TTL = -1; + class Table : public TableBase, public TableEntryEnumerable { public: Table(const DBConnector *db, const std::string &tableName); @@ -175,10 +178,20 @@ class Table : public TableBase, public TableEntryEnumerable { const std::vector &values, const std::string &op = "", const std::string &prefix = EMPTY_PREFIX); + + /* Set an entry in the DB directly and configure ttl for it (op not in use) */ + virtual void set(const std::string &key, + const std::vector &values, + const std::string &op, + const std::string &prefix, + const int64_t &ttl); + /* Delete an entry in the table */ virtual void del(const std::string &key, const std::string &op = "", const std::string &prefix = EMPTY_PREFIX); + /* Get the configured ttl value for key */ + bool ttl(const std::string &key, int64_t &reply_value); #ifdef SWIG // SWIG interface file (.i) globally rename map C++ `del` to python `delete`, diff --git a/tests/redis_ut.cpp b/tests/redis_ut.cpp index 8999a14eb..dd6292f0c 100644 --- a/tests/redis_ut.cpp +++ b/tests/redis_ut.cpp @@ -709,6 +709,50 @@ TEST(Table, table_separator_test) TableBasicTest("TABLE_UT_TEST", false); } +TEST(Table, ttl_test) +{ + string tableName = "TABLE_UT_TEST"; + DBConnector db("TEST_DB", 0, true); + RedisPipeline pipeline(&db); + Table t(&pipeline, tableName, true); + + clearDB(); + cout << "Starting table manipulations" << endl; + + string key_1 = "a"; + string key_2 = "b"; + vector values; + + for (int i = 1; i < 4; i++) + { + string field = "field_" + to_string(i); + string value = to_string(i); + values.push_back(make_pair(field, value)); + } + + int64_t initial_a_ttl = -1, initial_b_ttl = 200; + cout << "- Step 1. SET with custom ttl" << endl; + cout << "Set key [a] field_1:1 field_2:2 field_3:3 infinite ttl" << endl; + cout << "Set key [b] field_1:1 field_2:2 field_3:3 200 seconds ttl" << endl; + + t.set(key_1, values, "", "", initial_a_ttl); + t.set(key_2, values, "", "", initial_b_ttl); + t.flush(); + + cout << "- Step 2. GET_TTL_VALUES" << endl; + + int64_t a_ttl = 0, b_ttl = 0; + // Expect that we find the two entries confgured in the DB + EXPECT_EQ(true, t.ttl(key_1, a_ttl)); + EXPECT_EQ(true, t.ttl(key_2, b_ttl)); + + // Expect that TTL values are the ones configured earlier + EXPECT_EQ(a_ttl, initial_a_ttl); + EXPECT_EQ(b_ttl, initial_b_ttl); + + cout << "Done." << endl; +} + TEST(ProducerConsumer, Prefix) { std::string tableName = "tableName";