Skip to content

Commit d9b50ac

Browse files
Hrachya MughnetsyanShuotian Cheng
authored andcommitted
orchagent: Adding QosOrch and BufferOrch classes
* Class BufferOrch to handle buffer configuration * refactored Orch based class to contain common functions from QosOrch and BufferOrch * Class QosOrch * serialization for qos * qos functionality, including scheduler group processing * main.cpp * changed log level DEBUG back to INFO * portsqosorch.cpp, Port::getQueue * portsqosorch.cpp, Port::getPG * Samples * Added QOS and Buffer related configuration samples under swssconfig/sample.
1 parent 880cc60 commit d9b50ac

14 files changed

Lines changed: 2285 additions & 28 deletions

File tree

orchagent/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ else
1010
DBGFLAGS = -g
1111
endif
1212

13-
orchagent_SOURCES = main.cpp orchdaemon.cpp orch.cpp routeorch.cpp neighorch.cpp intfsorch.cpp portsorch.cpp
13+
orchagent_SOURCES = main.cpp orchdaemon.cpp orch.cpp routeorch.cpp neighorch.cpp intfsorch.cpp portsorch.cpp qosorch.cpp bufferorch.cpp
1414

1515
orchagent_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
1616
orchagent_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)

orchagent/bufferorch.cpp

Lines changed: 663 additions & 0 deletions
Large diffs are not rendered by default.

orchagent/bufferorch.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#ifndef SWSS_BUFFORCH_H
2+
#define SWSS_BUFFORCH_H
3+
4+
#include <map>
5+
#include "orch.h"
6+
#include "portsorch.h"
7+
8+
const std::string buffer_size_field_name = "size";
9+
const std::string buffer_pool_type_field_name = "type";
10+
const std::string buffer_pool_mode_field_name = "mode";
11+
const std::string buffer_pool_field_name = "pool";
12+
const std::string buffer_xon_field_name = "xon";
13+
const std::string buffer_xoff_field_name = "xoff";
14+
const std::string buffer_dynamic_th_field_name = "dynamic_th";
15+
const std::string buffer_static_th_field_name = "static_th";
16+
const std::string buffer_profile_field_name = "profile";
17+
const std::string buffer_value_ingress = "ingress";
18+
const std::string buffer_value_egress = "egress";
19+
const std::string buffer_pool_mode_dynamic_value = "dynamic";
20+
const std::string buffer_pool_mode_static_value = "static";
21+
const std::string range_specifier = "-";
22+
const std::string buffer_profile_list_field_name = "profile_list";
23+
const std::string comma = ",";
24+
25+
class BufferOrch : public Orch
26+
{
27+
public:
28+
BufferOrch(DBConnector *db, vector<string> &tableNames, PortsOrch *portsOrch);
29+
static type_map m_buffer_type_maps;
30+
private:
31+
typedef task_process_status (BufferOrch::*buffer_table_handler)(Consumer& consumer);
32+
typedef std::map<std::string, buffer_table_handler> buffer_table_handler_map;
33+
typedef std::pair<string, buffer_table_handler> buffer_handler_pair;
34+
35+
virtual void doTask(Consumer& consumer);
36+
void initTableHandlers();
37+
task_process_status processBufferPool(Consumer &consumer);
38+
task_process_status processBufferProfile(Consumer &consumer);
39+
task_process_status processQueue(Consumer &consumer);
40+
task_process_status processPriorityGroup(Consumer &consumer);
41+
task_process_status processIngressBufferProfileList(Consumer &consumer);
42+
task_process_status processEgressBufferProfileList(Consumer &consumer);
43+
bool parseIndexRange(const string &input, sai_uint32_t &range_low, sai_uint32_t &range_high);
44+
bool parseNameArray(const string &input, vector<string> &port_names);
45+
private:
46+
PortsOrch *m_portsOrch;
47+
buffer_table_handler_map m_bufferHandlerMap;
48+
};
49+
#endif /* SWSS_BUFFORCH_H */
50+

orchagent/main.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ sai_next_hop_api_t* sai_next_hop_api;
3131
sai_next_hop_group_api_t* sai_next_hop_group_api;
3232
sai_route_api_t* sai_route_api;
3333
sai_lag_api_t* sai_lag_api;
34+
sai_queue_api_t* sai_queue_api;
35+
sai_scheduler_api_t* sai_scheduler_api;
36+
sai_scheduler_group_api_t* sai_scheduler_group_api;
37+
sai_wred_api_t* sai_wred_api;
38+
sai_qos_map_api_t* sai_qos_map_api;
39+
sai_buffer_api_t* sai_buffer_api;
3440

3541
map<string, string> gProfileMap;
3642
sai_object_id_t gVirtualRouterId;
@@ -84,7 +90,13 @@ void initSaiApi()
8490
sai_api_query(SAI_API_NEXT_HOP_GROUP, (void **)&sai_next_hop_group_api);
8591
sai_api_query(SAI_API_ROUTE, (void **)&sai_route_api);
8692
sai_api_query(SAI_API_LAG, (void **)&sai_lag_api);
87-
93+
sai_api_query(SAI_API_QUEUE, (void **)&sai_queue_api);
94+
sai_api_query(SAI_API_SCHEDULER, (void **)&sai_scheduler_api);
95+
sai_api_query(SAI_API_WRED, (void **)&sai_wred_api);
96+
sai_api_query(SAI_API_QOS_MAPS, (void **)&sai_qos_map_api);
97+
sai_api_query(SAI_API_BUFFERS, (void **)&sai_buffer_api);
98+
sai_api_query(SAI_API_SCHEDULER_GROUP, (void **)&sai_scheduler_group_api);
99+
88100
sai_log_set(SAI_API_SWITCH, SAI_LOG_NOTICE);
89101
sai_log_set(SAI_API_VIRTUAL_ROUTER, SAI_LOG_NOTICE);
90102
sai_log_set(SAI_API_PORT, SAI_LOG_NOTICE);
@@ -96,6 +108,12 @@ void initSaiApi()
96108
sai_log_set(SAI_API_NEXT_HOP_GROUP, SAI_LOG_NOTICE);
97109
sai_log_set(SAI_API_ROUTE, SAI_LOG_NOTICE);
98110
sai_log_set(SAI_API_LAG, SAI_LOG_NOTICE);
111+
sai_log_set(SAI_API_QUEUE, SAI_LOG_NOTICE);
112+
sai_log_set(SAI_API_SCHEDULER, SAI_LOG_NOTICE);
113+
sai_log_set(SAI_API_WRED, SAI_LOG_NOTICE);
114+
sai_log_set(SAI_API_QOS_MAPS, SAI_LOG_NOTICE);
115+
sai_log_set(SAI_API_BUFFERS, SAI_LOG_NOTICE);
116+
sai_log_set(SAI_API_SCHEDULER_GROUP, SAI_LOG_NOTICE);
99117
}
100118

101119
void initDiagShell()

orchagent/orch.cpp

Lines changed: 192 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include "orch.h"
22
#include "logger.h"
33

4+
#include <sstream>
5+
#include <iostream>
6+
47
using namespace swss;
58

69
Orch::Orch(DBConnector *db, string tableName) :
@@ -13,7 +16,8 @@ Orch::Orch(DBConnector *db, string tableName) :
1316
Orch::Orch(DBConnector *db, vector<string> &tableNames) :
1417
m_db(db)
1518
{
16-
for( auto it = tableNames.begin(); it != tableNames.end(); it++) {
19+
for( auto it = tableNames.begin(); it != tableNames.end(); it++)
20+
{
1721
Consumer consumer(new ConsumerTable(m_db, *it));
1822
m_consumerMap.insert(ConsumerMapPair(*it, consumer));
1923
}
@@ -22,9 +26,8 @@ Orch::Orch(DBConnector *db, vector<string> &tableNames) :
2226
Orch::~Orch()
2327
{
2428
delete(m_db);
25-
for(auto it : m_consumerMap) {
29+
for(auto it : m_consumerMap)
2630
delete it.second.m_consumer;
27-
}
2831
}
2932

3033
std::vector<Selectable *> Orch::getSelectables()
@@ -48,10 +51,21 @@ bool Orch::hasSelectable(ConsumerTable *selectable) const
4851
return false;
4952
}
5053

54+
void Orch::dumpTuple(Consumer &consumer, KeyOpFieldsValuesTuple &tuple)
55+
{
56+
string debug_msg = "Full table content: " + consumer.m_consumer->getTableName() + " key : " + kfvKey(tuple) + " op : " + kfvOp(tuple);
57+
for (auto i = kfvFieldsValues(tuple).begin(); i != kfvFieldsValues(tuple).end(); i++)
58+
{
59+
debug_msg += " " + fvField(*i) + " : " + fvValue(*i);
60+
}
61+
SWSS_LOG_DEBUG("%s\n", debug_msg.c_str());
62+
}
63+
5164
bool Orch::execute(string tableName)
5265
{
5366
auto consumer_it = m_consumerMap.find(tableName);
54-
if(consumer_it == m_consumerMap.end()) {
67+
if(consumer_it == m_consumerMap.end())
68+
{
5569
SWSS_LOG_ERROR("Unrecognized tableName:%s\n", tableName.c_str());
5670
return false;
5771
}
@@ -62,16 +76,10 @@ bool Orch::execute(string tableName)
6276

6377
string key = kfvKey(new_data);
6478
string op = kfvOp(new_data);
65-
66-
#ifdef DEBUG
67-
string debug = "Table : " + consumer.m_consumer.getTableName() + " key : " + kfvKey(new_data) + " op : " + kfvOp(new_data);
68-
for (auto i = kfvFieldsValues(new_data).begin(); i != kfvFieldsValues(new_data).end(); i++)
69-
debug += " " + fvField(*i) + " : " + fvValue(*i);
70-
SWSS_LOG_DEBUG("%s\n", debug.c_str());
71-
#endif
79+
dumpTuple(consumer, new_data);
7280

7381
/* If a new task comes or if a DEL task comes, we directly put it into consumer.m_toSync map */
74-
if ( consumer.m_toSync.find(key) == consumer.m_toSync.end() || op == DEL_COMMAND)
82+
if( consumer.m_toSync.find(key) == consumer.m_toSync.end() || op == DEL_COMMAND)
7583
{
7684
consumer.m_toSync[key] = new_data;
7785
}
@@ -93,7 +101,7 @@ bool Orch::execute(string tableName)
93101
while (iu != existing_values.end())
94102
{
95103
string ofield = fvField(*iu);
96-
if (field == ofield)
104+
if(field == ofield)
97105
iu = existing_values.erase(iu);
98106
else
99107
iu++;
@@ -103,7 +111,119 @@ bool Orch::execute(string tableName)
103111
consumer.m_toSync[key] = KeyOpFieldsValuesTuple(key, op, existing_values);
104112
}
105113

106-
if (!consumer.m_toSync.empty())
114+
if(!consumer.m_toSync.empty())
115+
doTask(consumer);
116+
117+
return true;
118+
}
119+
bool Orch::tokenizeString(string str, const string &separator, vector<string> &tokens)
120+
{
121+
SWSS_LOG_ENTER();
122+
if(0 == separator.size())
123+
{
124+
SWSS_LOG_ERROR("Invalid separator passed in:%s\n", separator.c_str());
125+
return false;
126+
}
127+
if(string::npos == str.find(separator))
128+
{
129+
SWSS_LOG_ERROR("Specified separator:%s not found in input:%s\n", separator.c_str(), str.c_str());
130+
return false;
131+
}
132+
istringstream ss(str);
133+
string tmp;
134+
while (getline(ss, tmp, separator[0]))
135+
{
136+
SWSS_LOG_DEBUG("extracted token:%s", tmp.c_str());
137+
tokens.push_back(tmp);
138+
}
139+
return true;
140+
}
141+
142+
/*
143+
- Validates reference has proper format which is [table_name:object_name]
144+
- validates table_name exists
145+
- validates object with object_name exists
146+
*/
147+
bool Orch::parseReference(type_map &type_maps, string &ref_in, string &type_name, string &object_name)
148+
{
149+
SWSS_LOG_ENTER();
150+
SWSS_LOG_DEBUG("input:%s", ref_in.c_str());
151+
if(ref_in.size() < 3)
152+
{
153+
SWSS_LOG_ERROR("invalid reference received:%s\n", ref_in.c_str());
154+
return false;
155+
}
156+
if((ref_in[0] != ref_start) && (ref_in[ref_in.size()-1] != ref_end))
157+
{
158+
SWSS_LOG_ERROR("malformed reference:%s. Must be surrounded by [ ]\n", ref_in.c_str());
159+
return false;
160+
}
161+
string ref_content = ref_in.substr(1, ref_in.size() - 2);
162+
vector<string> tokens;
163+
if(!tokenizeString(ref_content, delimiter, tokens))
164+
{
165+
return false;
166+
}
167+
if(tokens.size() != 2)
168+
{
169+
SWSS_LOG_ERROR("malformed reference:%s. Must contain 2 tokens\n", ref_content.c_str());
170+
return false;
171+
}
172+
auto type_it = type_maps.find(tokens[0]);
173+
if(type_it == type_maps.end())
174+
{
175+
SWSS_LOG_ERROR("not recognized type:%s\n", tokens[0].c_str());
176+
return false;
177+
}
178+
auto obj_map = type_maps[tokens[0]];
179+
auto obj_it = obj_map->find(tokens[1]);
180+
if(obj_it == obj_map->end())
181+
{
182+
SWSS_LOG_ERROR("map:%s does not contain object with name:%s\n", tokens[0].c_str(), tokens[1].c_str());
183+
return false;
184+
}
185+
type_name = tokens[0];
186+
object_name = tokens[1];
187+
SWSS_LOG_DEBUG("parsed: type_name:%s, object_name:%s", type_name.c_str(), object_name.c_str());
188+
return true;
189+
}
190+
191+
ref_resolve_status Orch::resolveFieldRefValue(
192+
type_map &type_maps,
193+
const string &field_name,
194+
KeyOpFieldsValuesTuple &tuple,
195+
sai_object_id_t &sai_object)
196+
{
197+
SWSS_LOG_ENTER();
198+
size_t count = 0;
199+
for (auto i = kfvFieldsValues(tuple).begin(); i != kfvFieldsValues(tuple).end(); i++)
200+
{
201+
if(fvField(*i) == field_name)
202+
{
203+
SWSS_LOG_DEBUG("field:%s, value:%s", fvField(*i).c_str(), fvValue(*i).c_str());
204+
if(count > 1)
205+
{
206+
SWSS_LOG_ERROR("Singleton field with name:%s must have only 1 instance, actual count:%d\n", field_name.c_str(), count);
207+
return ref_resolve_status::multiple_instances;
208+
}
209+
string ref_type_name, object_name;
210+
if(!parseReference(type_maps, fvValue(*i), ref_type_name, object_name))
211+
{
212+
return ref_resolve_status::not_resolved;
213+
}
214+
sai_object = (*(type_maps[ref_type_name]))[object_name];
215+
count++;
216+
}
217+
}
218+
if(0 == count)
219+
{
220+
SWSS_LOG_NOTICE("field with name:%s not found\n", field_name.c_str());
221+
return ref_resolve_status::field_not_found;
222+
}
223+
return ref_resolve_status::success;
224+
}
225+
226+
if(!consumer.m_toSync.empty())
107227
doTask(consumer);
108228

109229
return true;
@@ -113,7 +233,63 @@ void Orch::doTask()
113233
{
114234
for(auto it : m_consumerMap)
115235
{
116-
if (!it.second.m_toSync.empty())
236+
if(!it.second.m_toSync.empty())
117237
doTask(it.second);
118238
}
119-
}
239+
}
240+
241+
// example: [BUFFER_PROFILE_TABLE:e_port.profile0],[BUFFER_PROFILE_TABLE:e_port.profile1]
242+
ref_resolve_status Orch::resolveFieldRefArray(
243+
type_map &type_maps,
244+
const string &field_name,
245+
KeyOpFieldsValuesTuple &tuple,
246+
vector<sai_object_id_t> &sai_object_arr)
247+
{
248+
SWSS_LOG_ENTER();
249+
size_t count = 0;
250+
sai_object_arr.clear();
251+
for (auto i = kfvFieldsValues(tuple).begin(); i != kfvFieldsValues(tuple).end(); i++)
252+
{
253+
if(fvField(*i) == field_name)
254+
{
255+
if(count > 1)
256+
{
257+
SWSS_LOG_ERROR("Singleton field with name:%s must have only 1 instance, actual count:%d\n", field_name.c_str(), count);
258+
return ref_resolve_status::multiple_instances;
259+
}
260+
string ref_type_name, object_name;
261+
string list = fvValue(*i);
262+
vector<string> list_items;
263+
if(list.find(list_item_delimiter) != string::npos)
264+
{
265+
if(!tokenizeString(list, list_item_delimiter, list_items))
266+
{
267+
SWSS_LOG_ERROR("Failed to tokenize buffer profile list:%s\n", list.c_str());
268+
return ref_resolve_status::failure;
269+
}
270+
}
271+
else
272+
{
273+
list_items.push_back(list);
274+
}
275+
for (size_t ind = 0; ind < list_items.size(); ind++)
276+
{
277+
if(!parseReference(type_maps, list_items[ind], ref_type_name, object_name))
278+
{
279+
SWSS_LOG_ERROR("Failed to parse profile reference:%s\n", list_items[ind].c_str());
280+
return ref_resolve_status::not_resolved;
281+
}
282+
sai_object_id_t sai_obj = (*(type_maps[ref_type_name]))[object_name];
283+
SWSS_LOG_DEBUG("Resolved to sai_object:0x%llx, type:%s, name:%s", sai_obj, ref_type_name.c_str(), object_name.c_str());
284+
sai_object_arr.push_back(sai_obj);
285+
}
286+
count++;
287+
}
288+
}
289+
if(0 == count)
290+
{
291+
SWSS_LOG_NOTICE("field with name:%s not found\n", field_name.c_str());
292+
return ref_resolve_status::field_not_found;
293+
}
294+
return ref_resolve_status::success;
295+
}

0 commit comments

Comments
 (0)