Skip to content

Commit f8b9385

Browse files
authored
Add support for fdb flush in sairedis (#288)
1 parent 2f2a2dd commit f8b9385

6 files changed

Lines changed: 328 additions & 2 deletions

File tree

lib/inc/sai_redis.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void check_notifications_pointers(
4545
// there is something wrong and we should fail
4646
#define GET_RESPONSE_TIMEOUT (6*60*1000)
4747

48+
extern std::string getSelectResultAsString(int result);
4849
extern void clear_local_state();
4950
extern void setRecording(bool record);
5051
extern sai_status_t setRecordingOutputDir(

lib/src/sai_redis_fdb.cpp

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,101 @@
11
#include "sai_redis.h"
22
#include "meta/saiserialize.h"
3+
#include "meta/saiattributelist.h"
4+
5+
sai_status_t internal_redis_flush_fdb_entries(
6+
_In_ sai_object_id_t switch_id,
7+
_In_ uint32_t attr_count,
8+
_In_ const sai_attribute_t *attr_list)
9+
{
10+
SWSS_LOG_ENTER();
11+
12+
std::vector<swss::FieldValueTuple> entry = SaiAttributeList::serialize_attr_list(
13+
SAI_OBJECT_TYPE_FDB_FLUSH,
14+
attr_count,
15+
attr_list,
16+
false);
17+
18+
std::string str_object_type = sai_serialize_object_type(SAI_OBJECT_TYPE_FDB_FLUSH);
19+
20+
std::string key = str_object_type + ":" + sai_serialize_object_id(switch_id);
21+
22+
SWSS_LOG_DEBUG("flush key: %s, fields: %lu", key.c_str(), entry.size());
23+
24+
if (g_record)
25+
{
26+
recordLine("f|" + key + "|" + joinFieldValues(entry));
27+
}
28+
29+
// flush is special, it will not put data
30+
// into asic view, only to message queue
31+
g_asicState->set(key, entry, "flush");
32+
33+
// wait for response
34+
35+
swss::Select s;
36+
37+
// get consumer will be reused for flush
38+
39+
s.addSelectable(g_redisGetConsumer.get());
40+
41+
while (true)
42+
{
43+
SWSS_LOG_DEBUG("wait for response");
44+
45+
swss::Selectable *sel;
46+
47+
int fd;
48+
49+
int result = s.select(&sel, &fd, GET_RESPONSE_TIMEOUT);
50+
51+
if (result == swss::Select::OBJECT)
52+
{
53+
swss::KeyOpFieldsValuesTuple kco;
54+
55+
g_redisGetConsumer->pop(kco);
56+
57+
const std::string &op = kfvOp(kco);
58+
const std::string &opkey = kfvKey(kco);
59+
60+
SWSS_LOG_DEBUG("response: op = %s, key = %s", opkey.c_str(), op.c_str());
61+
62+
if (op != "flushresponse") // ignore non response messages
63+
{
64+
continue;
65+
}
66+
67+
std::string str_sai_status = opkey;
68+
69+
sai_status_t status;
70+
71+
sai_deserialize_status(str_sai_status, status);
72+
73+
if (g_record)
74+
{
75+
const std::string &str_status = kfvKey(kco);
76+
77+
// first serialized is status
78+
recordLine("F|" + str_status);
79+
}
80+
81+
SWSS_LOG_DEBUG("flush status: %d", status);
82+
83+
return status;
84+
}
85+
86+
SWSS_LOG_ERROR("flush failed due to SELECT operation result: %s", getSelectResultAsString(result).c_str());
87+
break;
88+
}
89+
90+
if (g_record)
91+
{
92+
recordLine("F|SAI_STATUS_FAILURE");
93+
}
94+
95+
SWSS_LOG_ERROR("flush failed to get response");
96+
97+
return SAI_STATUS_FAILURE;
98+
}
399

4100
sai_status_t redis_flush_fdb_entries(
5101
_In_ sai_object_id_t switch_id,
@@ -10,7 +106,11 @@ sai_status_t redis_flush_fdb_entries(
10106

11107
SWSS_LOG_ENTER();
12108

13-
return SAI_STATUS_NOT_IMPLEMENTED;
109+
return meta_sai_flush_fdb_entries(
110+
switch_id,
111+
attr_count,
112+
attr_list,
113+
internal_redis_flush_fdb_entries);
14114
}
15115

16116
REDIS_GENERIC_QUAD_ENTRY(FDB_ENTRY,fdb_entry);

meta/sai_meta.cpp

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4737,3 +4737,154 @@ void meta_sai_on_fdb_event(
47374737
meta_sai_on_fdb_event_single(data[i]);
47384738
}
47394739
}
4740+
4741+
// FDB FLUSH
4742+
4743+
sai_status_t meta_sai_flush_fdb_entries(
4744+
_In_ sai_object_id_t switch_id,
4745+
_In_ uint32_t attr_count,
4746+
_In_ const sai_attribute_t *attr_list,
4747+
_In_ sai_flush_fdb_entries_fn flush_fdb_entries)
4748+
{
4749+
SWSS_LOG_ENTER();
4750+
4751+
if (flush_fdb_entries == NULL)
4752+
{
4753+
SWSS_LOG_ERROR("function pointer is NULL");
4754+
4755+
return SAI_STATUS_INVALID_PARAMETER;
4756+
}
4757+
4758+
if (attr_count > MAX_LIST_COUNT)
4759+
{
4760+
SWSS_LOG_ERROR("create attribute count is too large %u > then max list count %u", attr_count, MAX_LIST_COUNT);
4761+
4762+
return SAI_STATUS_INVALID_PARAMETER;
4763+
}
4764+
4765+
if (attr_count != 0 && attr_list == NULL)
4766+
{
4767+
SWSS_LOG_ERROR("attribute list is NULL");
4768+
4769+
return SAI_STATUS_INVALID_PARAMETER;
4770+
}
4771+
4772+
sai_object_type_t swot = sai_object_type_query(switch_id);
4773+
4774+
if (swot != SAI_OBJECT_TYPE_SWITCH)
4775+
{
4776+
SWSS_LOG_ERROR("object type for switch_id %s is %s",
4777+
sai_serialize_object_id(switch_id).c_str(),
4778+
sai_serialize_object_type(swot).c_str());
4779+
4780+
return SAI_STATUS_INVALID_PARAMETER;
4781+
}
4782+
4783+
if (!object_reference_exists(switch_id))
4784+
{
4785+
SWSS_LOG_ERROR("switch id %s don't exists",
4786+
sai_serialize_object_id(switch_id).c_str());
4787+
4788+
return SAI_STATUS_INVALID_PARAMETER;
4789+
}
4790+
4791+
// validate attributes
4792+
// - attribute list can be empty
4793+
// - validation is similar to "create" action but there is no
4794+
// post create step and no references are updated
4795+
// - fdb entries are updated in fdb notification
4796+
4797+
std::unordered_map<sai_attr_id_t, const sai_attribute_t*> attrs;
4798+
4799+
SWSS_LOG_DEBUG("attr count = %u", attr_count);
4800+
4801+
for (uint32_t idx = 0; idx < attr_count; ++idx)
4802+
{
4803+
const sai_attribute_t* attr = &attr_list[idx];
4804+
4805+
auto mdp = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_FDB_FLUSH, attr->id);
4806+
4807+
if (mdp == NULL)
4808+
{
4809+
SWSS_LOG_ERROR("unable to find attribute metadata SAI_OBJECT_TYPE_FDB_FLUSH:%d", attr->id);
4810+
4811+
return SAI_STATUS_INVALID_PARAMETER;
4812+
}
4813+
4814+
const sai_attribute_value_t& value = attr->value;
4815+
4816+
const sai_attr_metadata_t& md = *mdp;
4817+
4818+
META_LOG_DEBUG(md, "(fdbflush)");
4819+
4820+
if (attrs.find(attr->id) != attrs.end())
4821+
{
4822+
META_LOG_ERROR(md, "attribute id (%u) is defined on attr list multiple times", attr->id);
4823+
4824+
return SAI_STATUS_INVALID_PARAMETER;
4825+
}
4826+
4827+
attrs[attr->id] = attr;
4828+
4829+
if (md.flags != SAI_ATTR_FLAGS_CREATE_ONLY)
4830+
{
4831+
META_LOG_ERROR(md, "attr is expected to be marked as CREATE_ONLY");
4832+
4833+
return SAI_STATUS_INVALID_PARAMETER;
4834+
}
4835+
4836+
if (md.isconditional || md.validonlylength > 0)
4837+
{
4838+
META_LOG_ERROR(md, "attr should not be conditional or validonly");
4839+
4840+
return SAI_STATUS_INVALID_PARAMETER;
4841+
}
4842+
4843+
switch (md.attrvaluetype)
4844+
{
4845+
case SAI_ATTR_VALUE_TYPE_UINT16:
4846+
4847+
if (md.isvlan && (value.u16 >= 0xFFF || value.u16 == 0))
4848+
{
4849+
META_LOG_ERROR(md, "is vlan id but has invalid id %u", value.u16);
4850+
4851+
return SAI_STATUS_INVALID_PARAMETER;
4852+
}
4853+
4854+
break;
4855+
4856+
case SAI_ATTR_VALUE_TYPE_INT32:
4857+
4858+
if (md.isenum && !sai_metadata_is_allowed_enum_value(&md, value.s32))
4859+
{
4860+
META_LOG_ERROR(md, "is enum, but value %d not found on allowed values list", value.s32);
4861+
4862+
return SAI_STATUS_INVALID_PARAMETER;
4863+
}
4864+
4865+
break;
4866+
4867+
case SAI_ATTR_VALUE_TYPE_OBJECT_ID:
4868+
4869+
{
4870+
sai_status_t status = meta_generic_validation_objlist(md, switch_id, 1, &value.oid);
4871+
4872+
if (status != SAI_STATUS_SUCCESS)
4873+
{
4874+
return status;
4875+
}
4876+
4877+
break;
4878+
}
4879+
4880+
default:
4881+
4882+
META_LOG_THROW(md, "serialization type is not supported yet FIXME");
4883+
}
4884+
}
4885+
4886+
// there are no mandatory attributes
4887+
// there are no conditional attributes
4888+
4889+
return flush_fdb_entries(switch_id, attr_count, attr_list);
4890+
}

meta/sai_meta.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ extern void meta_sai_on_fdb_event(
158158
_In_ uint32_t count,
159159
_In_ sai_fdb_event_notification_data_t *data);
160160

161+
// FDB FLUSH
162+
163+
extern sai_status_t meta_sai_flush_fdb_entries(
164+
_In_ sai_object_id_t switch_id,
165+
_In_ uint32_t attr_count,
166+
_In_ const sai_attribute_t *attr_list,
167+
_In_ sai_flush_fdb_entries_fn flush_fdb_entries);
168+
161169
// UNIT TESTS HELPERS
162170

163171
/**

syncd/syncd.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,49 @@ sai_status_t processBulkEvent(
22592259
return status;
22602260
}
22612261

2262+
sai_status_t processFdbFlush(
2263+
_In_ const swss::KeyOpFieldsValuesTuple &kco)
2264+
{
2265+
SWSS_LOG_ENTER();
2266+
2267+
const std::string &key = kfvKey(kco);
2268+
const std::string &str_object_type = key.substr(0, key.find(":"));
2269+
const std::string &str_object_id = key.substr(key.find(":") + 1);
2270+
2271+
sai_object_id_t switch_vid;
2272+
2273+
sai_deserialize_object_id(str_object_id, switch_vid);
2274+
2275+
sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid);
2276+
2277+
const std::vector<swss::FieldValueTuple> &values = kfvFieldsValues(kco);
2278+
2279+
for (const auto &v: values)
2280+
{
2281+
SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str());
2282+
}
2283+
2284+
SaiAttributeList list(SAI_OBJECT_TYPE_FDB_FLUSH, values, false);
2285+
2286+
/*
2287+
* Attribute list can't be const since we will use it to translate VID to
2288+
* RID inplace.
2289+
*/
2290+
2291+
sai_attribute_t *attr_list = list.get_attr_list();
2292+
uint32_t attr_count = list.get_attr_count();
2293+
2294+
translate_vid_to_rid_list(SAI_OBJECT_TYPE_FDB_FLUSH, attr_count, attr_list);
2295+
2296+
sai_status_t status = sai_metadata_sai_fdb_api->flush_fdb_entries(switch_rid, attr_count, attr_list);
2297+
2298+
std::vector<swss::FieldValueTuple> en;
2299+
2300+
getResponse->set(sai_serialize_status(status), en, "flushresponse");
2301+
2302+
return status;
2303+
}
2304+
22622305
sai_status_t processEvent(
22632306
_In_ swss::ConsumerTable &consumer)
22642307
{
@@ -2330,6 +2373,10 @@ sai_status_t processEvent(
23302373
{
23312374
return processGetStatsEvent(kco);
23322375
}
2376+
else if (op == "flush")
2377+
{
2378+
return processFdbFlush(kco);
2379+
}
23332380
else
23342381
{
23352382
SWSS_LOG_THROW("api '%s' is not implemented", op.c_str());

vslib/src/sai_vs_fdb.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
#include "sai_vs.h"
22
#include "sai_vs_internal.h"
33

4+
sai_status_t internal_vs_flush_fdb_entries(
5+
_In_ sai_object_id_t switch_id,
6+
_In_ uint32_t attr_count,
7+
_In_ const sai_attribute_t *attr_list)
8+
{
9+
SWSS_LOG_ENTER();
10+
11+
// TODO implement actual flush (9 cases) with ntf generation (queue)
12+
// also update meta db here
13+
14+
SWSS_LOG_ERROR("not implemented");
15+
16+
return SAI_STATUS_NOT_IMPLEMENTED;
17+
}
18+
419
sai_status_t vs_flush_fdb_entries(
520
_In_ sai_object_id_t switch_id,
621
_In_ uint32_t attr_count,
@@ -10,7 +25,11 @@ sai_status_t vs_flush_fdb_entries(
1025

1126
SWSS_LOG_ENTER();
1227

13-
return SAI_STATUS_NOT_IMPLEMENTED;
28+
return meta_sai_flush_fdb_entries(
29+
switch_id,
30+
attr_count,
31+
attr_list,
32+
internal_vs_flush_fdb_entries);
1433
}
1534

1635
VS_GENERIC_QUAD_ENTRY(FDB_ENTRY,fdb_entry);

0 commit comments

Comments
 (0)