Skip to content

Commit

Permalink
Implement bulk create/remove for nhgm/route/fdb (sonic-net#269)
Browse files Browse the repository at this point in the history
* Implement sai_bulk_remove_next_hop_group_members

* Implement sai_bulk_remove_route_entry

* Implement sai_bulk_create/remove_fdb_entry

Signed-off-by: Qi Luo <qiluo-msft@users.noreply.github.com>
  • Loading branch information
qiluo-msft authored Dec 1, 2017
1 parent 4204822 commit 345f179
Show file tree
Hide file tree
Showing 8 changed files with 432 additions and 24 deletions.
11 changes: 11 additions & 0 deletions lib/inc/sai_redis.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ sai_status_t redis_generic_remove_neighbor_entry(
sai_status_t redis_generic_remove_route_entry(
_In_ const sai_route_entry_t* route_entry);

sai_status_t redis_bulk_generic_remove(
_In_ sai_object_type_t object_type,
_In_ uint32_t object_count,
_In_ const sai_object_id_t *object_id, /* array */
_Inout_ sai_status_t *object_statuses) /* array */;

sai_status_t internal_redis_bulk_generic_remove(
_In_ sai_object_type_t object_type,
_In_ const std::vector<std::string> &serialized_object_ids,
_Out_ sai_status_t *object_statuses) /* array */;

// SET

sai_status_t redis_generic_set(
Expand Down
17 changes: 15 additions & 2 deletions lib/inc/sairedis.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ sai_status_t sai_bulk_get_route_entry_attribute(
_In_ sai_bulk_op_type_t type,
_Out_ sai_status_t *object_statuses);

sai_status_t redis_bulk_object_create_next_hop_group_members(
sai_status_t sai_bulk_create_next_hop_group_members(
_In_ sai_object_id_t switch_id,
_In_ uint32_t object_count,
_In_ const uint32_t *attr_count,
Expand All @@ -226,10 +226,23 @@ sai_status_t redis_bulk_object_create_next_hop_group_members(
_Out_ sai_object_id_t *object_id,
_Out_ sai_status_t *object_statuses);

sai_status_t redis_bulk_object_remove_next_hop_group_members(
sai_status_t sai_bulk_remove_next_hop_group_members(
_In_ uint32_t object_count,
_In_ const sai_object_id_t *object_id,
_In_ sai_bulk_op_type_t type,
_Out_ sai_status_t *object_statuses);

sai_status_t sai_bulk_create_fdb_entry(
_In_ uint32_t object_count,
_In_ const sai_fdb_entry_t *fdb_entry,
_In_ const uint32_t *attr_count,
_In_ const sai_attribute_t *const *attr_list,
_In_ sai_bulk_op_type_t type,
_Out_ sai_status_t *object_statuses);

sai_status_t sai_bulk_remove_fdb_entry(
_In_ uint32_t object_count,
_In_ const sai_fdb_entry_t *fdb_entry,
_In_ sai_bulk_op_type_t type,
_Out_ sai_status_t *object_statuses);
#endif // __SAIREDIS__
159 changes: 159 additions & 0 deletions lib/src/sai_redis_fdb.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "sai_redis.h"
#include "meta/saiserialize.h"

sai_status_t redis_flush_fdb_entries(
_In_ sai_object_id_t switch_id,
Expand All @@ -20,3 +21,161 @@ const sai_fdb_api_t redis_fdb_api = {

redis_flush_fdb_entries,
};

sai_status_t redis_dummy_create_fdb_entry(
_In_ const sai_fdb_entry_t *fdb_entry,
_In_ uint32_t attr_count,
_In_ const sai_attribute_t *attr_list)
{
SWSS_LOG_ENTER();

/*
* Since we are using validation for each fdb in bulk operations, we
* can't execute actual CREATE, we need to do dummy create and then introduce
* internal bulk_create operation that will only touch redis db only once.
* So we are returning success here.
*/

return SAI_STATUS_SUCCESS;
}

sai_status_t sai_bulk_create_fdb_entry(
_In_ uint32_t object_count,
_In_ const sai_fdb_entry_t *fdb_entry,
_In_ const uint32_t *attr_count,
_In_ const sai_attribute_t *const *attr_list,
_In_ sai_bulk_op_type_t type,
_Out_ sai_status_t *object_statuses)
{
std::lock_guard<std::mutex> lock(g_apimutex);

SWSS_LOG_ENTER();

if (object_count < 1)
{
SWSS_LOG_ERROR("expected at least 1 object to create");

return SAI_STATUS_INVALID_PARAMETER;
}

if (fdb_entry == NULL)
{
SWSS_LOG_ERROR("fdb_entry is NULL");

return SAI_STATUS_INVALID_PARAMETER;
}

if (attr_count == NULL)
{
SWSS_LOG_ERROR("attr_count is NULL");

return SAI_STATUS_INVALID_PARAMETER;
}

if (attr_list == NULL)
{
SWSS_LOG_ERROR("attr_list is NULL");

return SAI_STATUS_INVALID_PARAMETER;
}

switch (type)
{
case SAI_BULK_OP_TYPE_STOP_ON_ERROR:
case SAI_BULK_OP_TYPE_INGORE_ERROR:
// ok
break;

default:

SWSS_LOG_ERROR("invalid bulk operation type %d", type);

return SAI_STATUS_INVALID_PARAMETER;
}

if (object_statuses == NULL)
{
SWSS_LOG_ERROR("object_statuses is NULL");

return SAI_STATUS_INVALID_PARAMETER;
}

std::vector<std::string> serialized_object_ids;

for (uint32_t idx = 0; idx < object_count; ++idx)
{
/*
* At the beginning set all statuses to not executed.
*/

object_statuses[idx] = SAI_STATUS_NOT_EXECUTED;

serialized_object_ids.push_back(
sai_serialize_fdb_entry(fdb_entry[idx]));
}

for (uint32_t idx = 0; idx < object_count; ++idx)
{
sai_status_t status =
meta_sai_create_fdb_entry(
&fdb_entry[idx],
attr_count[idx],
attr_list[idx],
&redis_dummy_create_fdb_entry);

object_statuses[idx] = status;

if (status != SAI_STATUS_SUCCESS)
{
// TODO add attr id and value

SWSS_LOG_ERROR("failed on index %u: %s",
idx,
serialized_object_ids[idx].c_str());

if (type == SAI_BULK_OP_TYPE_STOP_ON_ERROR)
{
SWSS_LOG_NOTICE("stop on error since previous operation failed");
break;
}
}
}

/*
* TODO: we need to record operation type
*/

return internal_redis_bulk_generic_create(
SAI_OBJECT_TYPE_ROUTE_ENTRY,
serialized_object_ids,
attr_count,
attr_list,
object_statuses);
}

sai_status_t sai_bulk_remove_fdb_entry(
_In_ uint32_t object_count,
_In_ const sai_fdb_entry_t *fdb_entry,
_In_ sai_bulk_op_type_t type,
_Out_ sai_status_t *object_statuses)
{
std::lock_guard<std::mutex> lock(g_apimutex);

SWSS_LOG_ENTER();

std::vector<std::string> serialized_object_ids;

for (uint32_t idx = 0; idx < object_count; ++idx)
{
/*
* At the beginning set all statuses to not executed.
*/

object_statuses[idx] = SAI_STATUS_NOT_EXECUTED;

serialized_object_ids.push_back(
sai_serialize_fdb_entry(fdb_entry[idx]));
}

return internal_redis_bulk_generic_remove(SAI_OBJECT_TYPE_ROUTE_ENTRY, serialized_object_ids, object_statuses);
}
86 changes: 86 additions & 0 deletions lib/src/sai_redis_generic_remove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,92 @@ sai_status_t redis_generic_remove(
return status;
}

sai_status_t redis_bulk_generic_remove(
_In_ sai_object_type_t object_type,
_In_ uint32_t object_count,
_In_ const sai_object_id_t *object_id, /* array */
_Out_ sai_status_t *object_statuses) /* array */
{
SWSS_LOG_ENTER();

std::vector<std::string> serialized_object_ids;

// on create vid is put in db by syncd
for (uint32_t idx = 0; idx < object_count; idx++)
{
std::string str_object_id = sai_serialize_object_id(object_id[idx]);
serialized_object_ids.push_back(str_object_id);
}

return internal_redis_bulk_generic_remove(
object_type,
serialized_object_ids,
object_statuses);
}

sai_status_t internal_redis_bulk_generic_remove(
_In_ sai_object_type_t object_type,
_In_ const std::vector<std::string> &serialized_object_ids,
_Out_ sai_status_t *object_statuses) /* array */
{
SWSS_LOG_ENTER();

std::string str_object_type = sai_serialize_object_type(object_type);

std::vector<swss::FieldValueTuple> entries;

/*
* We are recording all entries and their statuses, but we send to sairedis
* only those that succeeded metadata check, since only those will be
* executed on syncd, so there is no need with bothering decoding statuses
* on syncd side.
*/

for (size_t idx = 0; idx < serialized_object_ids.size(); ++idx)
{
std::string str_attr = "";

swss::FieldValueTuple fvtNoStatus(serialized_object_ids[idx], str_attr);

entries.push_back(fvtNoStatus);
}

/*
* We are adding number of entries to actualy add ':' to be compatible
* with previous
*/

if (g_record)
{
std::string joined;

for (const auto &e: entries)
{
// ||obj_id|attr=val|attr=val||obj_id|attr=val|attr=val

joined += "||" + fvField(e) + "|" + fvValue(e);
}

/*
* Capital 'C' stads for bulk CREATE operation.
*/

recordLine("C|" + str_object_type + joined);
}

// key: object_type:count
// field: object_id
// value: object_attrs
std::string key = str_object_type + ":" + std::to_string(entries.size());

if (entries.size())
{
g_asicState->set(key, entries, "bulkremove");
}

return SAI_STATUS_SUCCESS;
}

sai_status_t redis_generic_remove_fdb_entry(
_In_ const sai_fdb_entry_t* fdb_entry)
{
Expand Down
10 changes: 5 additions & 5 deletions lib/src/sai_redis_nexthopgroup.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "sai_redis.h"

sai_status_t redis_bulk_object_create_next_hop_group_members(
sai_status_t sai_bulk_create_next_hop_group_members(
_In_ sai_object_id_t switch_id,
_In_ uint32_t object_count,
_In_ const uint32_t *attr_count,
Expand All @@ -17,7 +17,7 @@ sai_status_t redis_bulk_object_create_next_hop_group_members(
, switch_id, attr_count, attrs, object_statuses);
}

sai_status_t redis_bulk_object_remove_next_hop_group_members(
sai_status_t sai_bulk_remove_next_hop_group_members(
_In_ uint32_t object_count,
_In_ const sai_object_id_t *object_id,
_In_ sai_bulk_op_type_t type,
Expand All @@ -27,7 +27,7 @@ sai_status_t redis_bulk_object_remove_next_hop_group_members(

SWSS_LOG_ENTER();

return SAI_STATUS_NOT_IMPLEMENTED;
return redis_bulk_generic_remove(SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER, object_count, object_id, object_statuses);
}

REDIS_GENERIC_QUAD(NEXT_HOP_GROUP,next_hop_group);
Expand All @@ -39,6 +39,6 @@ const sai_next_hop_group_api_t redis_next_hop_group_api = {
REDIS_GENERIC_QUAD_API(next_hop_group_member)

// TODO: upstream signiture fix to SAI repo
(sai_bulk_object_create_fn)redis_bulk_object_create_next_hop_group_members,
redis_bulk_object_remove_next_hop_group_members,
(sai_bulk_object_create_fn)sai_bulk_create_next_hop_group_members,
sai_bulk_remove_next_hop_group_members,
};
22 changes: 21 additions & 1 deletion lib/src/sai_redis_route.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ REDIS_GENERIC_QUAD_ENTRY(ROUTE_ENTRY,route_entry);
const sai_route_api_t redis_route_api = {

REDIS_GENERIC_QUAD_API(route_entry)

// TODO: uncomment block after SAI 1.2
// sai_bulk_create_route_entry,
// sai_bulk_remove_route_entry,
// sai_bulk_set_route_entry_attribute,
// sai_bulk_get_route_entry_attribute
};

sai_status_t redis_dummy_create_route_entry(
Expand Down Expand Up @@ -151,7 +157,21 @@ sai_status_t sai_bulk_remove_route_entry(

SWSS_LOG_ENTER();

return SAI_STATUS_NOT_IMPLEMENTED;
std::vector<std::string> serialized_object_ids;

for (uint32_t idx = 0; idx < object_count; ++idx)
{
/*
* At the beginning set all statuses to not executed.
*/

object_statuses[idx] = SAI_STATUS_NOT_EXECUTED;

serialized_object_ids.push_back(
sai_serialize_route_entry(route_entry[idx]));
}

return internal_redis_bulk_generic_remove(SAI_OBJECT_TYPE_ROUTE_ENTRY, serialized_object_ids, object_statuses);
}

sai_status_t redis_dummy_set_route_entry(
Expand Down
Loading

0 comments on commit 345f179

Please sign in to comment.