Skip to content

Commit f05e8e9

Browse files
authored
[SRv6] add MySID counters support (#3601)
* SRv6: add MySID counters support What I did Extended srv6orch to support SRv6 MySID counters (utilizing flex counter infrastructure) Why I did it To support SRv6 MySID counters
1 parent a0bd39e commit f05e8e9

6 files changed

Lines changed: 316 additions & 19 deletions

File tree

orchagent/flex_counter/flex_counter_manager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const unordered_map<CounterType, string> FlexCounterManager::counter_id_field_lo
5050
{ CounterType::HOSTIF_TRAP, FLOW_COUNTER_ID_LIST },
5151
{ CounterType::ROUTE, FLOW_COUNTER_ID_LIST },
5252
{ CounterType::ENI, ENI_COUNTER_ID_LIST },
53+
{ CounterType::SRV6, SRV6_COUNTER_ID_LIST },
5354
};
5455

5556
FlexManagerDirectory g_FlexManagerDirectory;

orchagent/flex_counter/flex_counter_manager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ enum class CounterType
3838
TUNNEL,
3939
HOSTIF_TRAP,
4040
ROUTE,
41-
ENI
41+
ENI,
42+
SRV6
4243
};
4344

4445
extern bool gTraditionalFlexCounter;

orchagent/flexcounterorch.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ extern BufferOrch *gBufferOrch;
2727
extern Directory<Orch*> gDirectory;
2828
extern CoppOrch *gCoppOrch;
2929
extern FlowCounterRouteOrch *gFlowCounterRouteOrch;
30+
extern Srv6Orch *gSrv6Orch;
3031
extern sai_object_id_t gSwitchId;
3132

3233
#define FLEX_COUNTER_DELAY_SEC 60
@@ -46,6 +47,7 @@ extern sai_object_id_t gSwitchId;
4647
#define ENI_KEY "ENI"
4748
#define WRED_QUEUE_KEY "WRED_ECN_QUEUE"
4849
#define WRED_PORT_KEY "WRED_ECN_PORT"
50+
#define SRV6_KEY "SRV6"
4951

5052
unordered_map<string, string> flexCounterGroupMap =
5153
{
@@ -71,6 +73,7 @@ unordered_map<string, string> flexCounterGroupMap =
7173
{"ENI", ENI_STAT_COUNTER_FLEX_COUNTER_GROUP},
7274
{"WRED_ECN_PORT", WRED_PORT_STAT_COUNTER_FLEX_COUNTER_GROUP},
7375
{"WRED_ECN_QUEUE", WRED_QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP},
76+
{SRV6_KEY, SRV6_STAT_COUNTER_FLEX_COUNTER_GROUP},
7477
};
7578

7679

@@ -270,6 +273,10 @@ void FlexCounterOrch::doTask(Consumer &consumer)
270273
m_route_flow_counter_enabled = false;
271274
}
272275
}
276+
if (gSrv6Orch && (key == SRV6_KEY))
277+
{
278+
gSrv6Orch->setCountersState((value == "enable"));
279+
}
273280

274281
gPortsOrch->flushCounters();
275282
setFlexCounterGroupOperation(flexCounterGroupMap[key], value);

orchagent/srv6orch.cpp

Lines changed: 246 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "crmorch.h"
1111
#include "subscriberstatetable.h"
1212
#include "redisutility.h"
13+
#include "flex_counter_manager.h"
14+
#include "flow_counter_handler.h"
1315

1416
using namespace std;
1517
using namespace swss;
@@ -21,6 +23,9 @@ using namespace swss;
2123
#define LOCATOR_DEFAULT_FUNC_LEN "16"
2224
#define LOCATOR_DEFAULT_ARG_LEN "0"
2325

26+
#define SRV6_FLEX_COUNTER_UPDATE_TIMER 1
27+
#define SRV6_STAT_COUNTER_POLLING_INTERVAL_MS 10000
28+
2429
extern sai_object_id_t gSwitchId;
2530
extern sai_object_id_t gVirtualRouterId;
2631
extern sai_object_id_t gUnderlayIfId;
@@ -31,6 +36,7 @@ extern sai_router_interface_api_t* sai_router_intfs_api;
3136

3237
extern RouteOrch *gRouteOrch;
3338
extern CrmOrch *gCrmOrch;
39+
extern bool gTraditionalFlexCounter;
3440

3541
const map<string, sai_my_sid_entry_endpoint_behavior_t> end_behavior_map =
3642
{
@@ -89,6 +95,222 @@ static bool mySidDscpModeToSai(const string& mode, sai_tunnel_dscp_mode_t& sai_m
8995
return false;
9096
}
9197

98+
Srv6Orch::Srv6Orch(DBConnector *cfgDb, DBConnector *applDb, const vector<TableConnector>& tables, SwitchOrch *switchOrch, VRFOrch *vrfOrch, NeighOrch *neighOrch):
99+
Orch(tables),
100+
m_vrfOrch(vrfOrch),
101+
m_switchOrch(switchOrch),
102+
m_neighOrch(neighOrch),
103+
m_sidTable(applDb, APP_SRV6_SID_LIST_TABLE_NAME),
104+
m_mysidTable(applDb, APP_SRV6_MY_SID_TABLE_NAME),
105+
m_piccontextTable(applDb, APP_PIC_CONTEXT_TABLE_NAME),
106+
m_mysidCfgTable(cfgDb, CFG_SRV6_MY_SID_TABLE_NAME),
107+
m_locatorCfgTable(cfgDb, CFG_SRV6_MY_LOCATOR_TABLE_NAME),
108+
m_counter_manager(SRV6_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, SRV6_STAT_COUNTER_POLLING_INTERVAL_MS, false)
109+
{
110+
m_neighOrch->attach(this);
111+
112+
initializeCounters();
113+
}
114+
115+
Srv6Orch::~Srv6Orch()
116+
{
117+
m_neighOrch->detach(this);
118+
}
119+
120+
void Srv6Orch::initializeCounters()
121+
{
122+
m_mysid_counters_supported = queryMySidCountersCapability();
123+
if (!m_mysid_counters_supported)
124+
{
125+
SWSS_LOG_INFO("SRv6 counters are not supported on this platform");
126+
return;
127+
}
128+
129+
m_asic_db = make_shared<DBConnector>("ASIC_DB", 0);
130+
m_counter_db = make_shared<DBConnector>("COUNTERS_DB", 0);
131+
m_mysid_counters_table = make_unique<Table>(m_counter_db.get(), COUNTERS_SRV6_NAME_MAP);
132+
133+
if (gTraditionalFlexCounter)
134+
{
135+
m_vid_to_rid_table = make_unique<Table>(m_asic_db.get(), "VIDTORID");
136+
}
137+
138+
m_counter_update_timer = new SelectableTimer(timespec { .tv_sec = SRV6_FLEX_COUNTER_UPDATE_TIMER , .tv_nsec = 0 });
139+
auto et = new ExecutableTimer(m_counter_update_timer, this, "SRV6_FLEX_COUNTER_UPDATE_TIMER");
140+
Orch::addExecutor(et);
141+
}
142+
143+
bool Srv6Orch::queryMySidCountersCapability() const
144+
{
145+
sai_attr_capability_t capability;
146+
sai_status_t status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_MY_SID_ENTRY, SAI_MY_SID_ENTRY_ATTR_COUNTER_ID, &capability);
147+
if (status != SAI_STATUS_SUCCESS)
148+
{
149+
SWSS_LOG_WARN("Could not query SRv6 MySID entry attribute SAI_MY_SID_ENTRY_ATTR_COUNTER_ID %d", status);
150+
return false;
151+
}
152+
153+
return capability.set_implemented && capability.create_implemented;
154+
}
155+
156+
157+
bool Srv6Orch::getMySidCountersEnabled() const
158+
{
159+
return m_mysid_counters_enabled;
160+
}
161+
162+
bool Srv6Orch::getMySidCountersSupported() const
163+
{
164+
return m_mysid_counters_supported;
165+
}
166+
167+
IpAddress Srv6Orch::getMySidAddress(const sai_my_sid_entry_t& sai_entry) const
168+
{
169+
ip_addr_t ip_addr = {};
170+
ip_addr.family = AF_INET6;
171+
memcpy(&ip_addr.ip_addr.ipv6_addr, sai_entry.sid, sizeof(ip_addr.ip_addr.ipv6_addr));
172+
173+
return IpAddress(ip_addr);
174+
}
175+
176+
string Srv6Orch::getMySidCounterKey(const sai_my_sid_entry_t& sai_entry) const
177+
{
178+
auto mysid_addr = getMySidAddress(sai_entry).to_string();
179+
auto locator_cfg = getMySidEntryLocatorCfg(sai_entry);
180+
return getMySidPrefix(mysid_addr, locator_cfg);
181+
}
182+
183+
bool Srv6Orch::addMySidCounter(const sai_my_sid_entry_t& sai_entry, sai_object_id_t& counter_oid)
184+
{
185+
SWSS_LOG_ENTER();
186+
187+
if (!FlowCounterHandler::createGenericCounter(counter_oid))
188+
{
189+
SWSS_LOG_ERROR("Failed to create SAI counter for SRv6 MySID entry");
190+
return false;
191+
}
192+
193+
auto key = getMySidCounterKey(sai_entry);
194+
vector<FieldValueTuple> fvs = {
195+
{key, sai_serialize_object_id(counter_oid)}
196+
};
197+
198+
m_mysid_counters_table->set("", fvs);
199+
200+
auto was_empty = m_pending_counters.empty();
201+
m_pending_counters[counter_oid] = key;
202+
203+
if (was_empty)
204+
{
205+
m_counter_update_timer->start();
206+
}
207+
208+
return true;
209+
}
210+
211+
void Srv6Orch::removeMySidCounter(const sai_my_sid_entry_t& sai_entry, sai_object_id_t& counter_oid)
212+
{
213+
SWSS_LOG_ENTER();
214+
215+
if (counter_oid == SAI_NULL_OBJECT_ID)
216+
{
217+
return;
218+
}
219+
220+
auto key = getMySidCounterKey(sai_entry);
221+
222+
m_mysid_counters_table->hdel("", key);
223+
224+
auto was_pending = m_pending_counters.erase(counter_oid) == 1;
225+
if (!was_pending)
226+
{
227+
SWSS_LOG_INFO("Unregistering SRv6 counter for %s, oid %s", key.c_str(), sai_serialize_object_id(counter_oid).c_str());
228+
m_counter_manager.clearCounterIdList(counter_oid);
229+
}
230+
231+
FlowCounterHandler::removeGenericCounter(counter_oid);
232+
counter_oid = SAI_NULL_OBJECT_ID;
233+
}
234+
235+
void Srv6Orch::setMySidEntryCounter(const sai_my_sid_entry_t& sai_entry, sai_object_id_t counter_oid)
236+
{
237+
SWSS_LOG_ENTER();
238+
239+
sai_attribute_t attr;
240+
attr.id = SAI_MY_SID_ENTRY_ATTR_COUNTER_ID;
241+
attr.value.oid = counter_oid;
242+
243+
auto status = sai_srv6_api->set_my_sid_entry_attribute(&sai_entry, &attr);
244+
if (status != SAI_STATUS_SUCCESS)
245+
{
246+
SWSS_LOG_ERROR("Failed to set my_sid entry counter oid to %s, rc: %s", sai_serialize_object_id(counter_oid).c_str(), sai_serialize_status(status).c_str());
247+
}
248+
}
249+
250+
void Srv6Orch::setCountersState(bool enable)
251+
{
252+
SWSS_LOG_ENTER();
253+
254+
if (!getMySidCountersSupported())
255+
{
256+
SWSS_LOG_WARN("Ignoring SRv6 counters state change as they are not supported on this platform");
257+
return;
258+
}
259+
260+
if (enable == m_mysid_counters_enabled)
261+
{
262+
return;
263+
}
264+
265+
SWSS_LOG_NOTICE("Setting SRv6 MySID counters state to %s", enable ? "enabled" : "disabled");
266+
267+
for (auto& mysid : srv6_my_sid_table_)
268+
{
269+
const auto& sai_entry = mysid.second.entry;
270+
auto &counter_oid = mysid.second.counter;
271+
272+
if (enable)
273+
{
274+
addMySidCounter(sai_entry, counter_oid);
275+
setMySidEntryCounter(sai_entry, counter_oid);
276+
} else {
277+
setMySidEntryCounter(sai_entry, SAI_NULL_OBJECT_ID);
278+
removeMySidCounter(sai_entry, counter_oid);
279+
}
280+
}
281+
282+
m_mysid_counters_enabled = enable;
283+
}
284+
285+
void Srv6Orch::doTask(SelectableTimer &timer)
286+
{
287+
SWSS_LOG_ENTER();
288+
289+
string value;
290+
for (auto it = m_pending_counters.begin(); it != m_pending_counters.end();)
291+
{
292+
const auto oid = sai_serialize_object_id(it->first);
293+
if (!gTraditionalFlexCounter || m_vid_to_rid_table->hget("", oid, value))
294+
{
295+
SWSS_LOG_INFO("Registering SRv6 counter for %s, oid %s", it->second.c_str(), oid.c_str());
296+
297+
unordered_set<string> counter_stats;
298+
FlowCounterHandler::getGenericCounterStatIdList(counter_stats);
299+
m_counter_manager.setCounterIdList(it->first, CounterType::SRV6, counter_stats);
300+
it = m_pending_counters.erase(it);
301+
}
302+
else
303+
{
304+
++it;
305+
}
306+
}
307+
308+
if (m_pending_counters.empty())
309+
{
310+
m_counter_update_timer->stop();
311+
}
312+
}
313+
92314
MySidLocatorCfg Srv6Orch::getMySidEntryLocatorCfg(const sai_my_sid_entry_t& sai_entry) const
93315
{
94316
return {
@@ -99,6 +321,12 @@ MySidLocatorCfg Srv6Orch::getMySidEntryLocatorCfg(const sai_my_sid_entry_t& sai_
99321
};
100322
}
101323

324+
325+
string Srv6Orch::getMySidPrefix(const string& my_sid_addr, const MySidLocatorCfg& locator_cfg) const
326+
{
327+
return my_sid_addr + "/" + to_string(locator_cfg.block_len + locator_cfg.node_len + locator_cfg.func_len);
328+
}
329+
102330
bool Srv6Orch::getLocatorCfgFromDb(const string& locator, MySidLocatorCfg& cfg)
103331
{
104332
vector<FieldValueTuple> fvs;
@@ -201,7 +429,7 @@ void Srv6Orch::mySidCfgCacheRefresh()
201429

202430
bool Srv6Orch::getMySidEntryDscpMode(const string& my_sid_addr, const MySidLocatorCfg& locator_cfg, sai_tunnel_dscp_mode_t& dscp_mode)
203431
{
204-
auto my_sid_prefix = my_sid_addr + "/" + to_string(locator_cfg.block_len + locator_cfg.node_len + locator_cfg.func_len);
432+
auto my_sid_prefix = getMySidPrefix(my_sid_addr, locator_cfg);
205433

206434
auto cfg_cache = my_sid_dscp_cfg_cache_.equal_range(my_sid_prefix);
207435
if (cfg_cache.first == my_sid_dscp_cfg_cache_.end())
@@ -1356,13 +1584,28 @@ bool Srv6Orch::createUpdateMysidEntry(string my_sid_string, const string dt_vrf,
13561584
sai_status_t status = SAI_STATUS_SUCCESS;
13571585
if (!entry_exists)
13581586
{
1587+
sai_object_id_t counter_oid = SAI_NULL_OBJECT_ID;
1588+
if (getMySidCountersSupported() && getMySidCountersEnabled())
1589+
{
1590+
auto ok = addMySidCounter(my_sid_entry, counter_oid);
1591+
if (!ok)
1592+
{
1593+
return false;
1594+
}
1595+
1596+
attr.id = SAI_MY_SID_ENTRY_ATTR_COUNTER_ID;
1597+
attr.value.oid = counter_oid;
1598+
attributes.push_back(attr);
1599+
}
1600+
13591601
status = sai_srv6_api->create_my_sid_entry(&my_sid_entry, (uint32_t) attributes.size(), attributes.data());
13601602
if (status != SAI_STATUS_SUCCESS)
13611603
{
13621604
SWSS_LOG_ERROR("Failed to create my_sid entry %s, rv %d", key_string.c_str(), status);
13631605
return false;
13641606
}
13651607
gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_SRV6_MY_SID_ENTRY);
1608+
srv6_my_sid_table_[key_string].counter = counter_oid;
13661609
}
13671610
else
13681611
{
@@ -1415,6 +1658,7 @@ bool Srv6Orch::deleteMysidEntry(const string my_sid_string)
14151658
return false;
14161659
}
14171660
sai_my_sid_entry_t my_sid_entry = srv6_my_sid_table_[my_sid_string].entry;
1661+
sai_object_id_t& counter = srv6_my_sid_table_[my_sid_string].counter;
14181662

14191663
SWSS_LOG_NOTICE("MySid Delete: sid %s", my_sid_string.c_str());
14201664
status = sai_srv6_api->remove_my_sid_entry(&my_sid_entry);
@@ -1425,6 +1669,7 @@ bool Srv6Orch::deleteMysidEntry(const string my_sid_string)
14251669
}
14261670
gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_SRV6_MY_SID_ENTRY);
14271671

1672+
removeMySidCounter(my_sid_entry, counter);
14281673

14291674
auto endBehavior = srv6_my_sid_table_[my_sid_string].endBehavior;
14301675
/* Decrease VRF refcount */

0 commit comments

Comments
 (0)