Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copp sflow changes #1011

Merged
merged 8 commits into from
Oct 28, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 221 additions & 5 deletions orchagent/copporch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <inttypes.h>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace swss;
using namespace std;
Expand Down Expand Up @@ -88,14 +89,15 @@ const vector<sai_hostif_trap_type_t> default_trap_ids = {
SAI_HOSTIF_TRAP_TYPE_TTL_ERROR
};

CoppOrch::CoppOrch(DBConnector *db, string tableName) :
Orch(db, tableName)
CoppOrch::CoppOrch(vector<TableConnector> &tableConnectors) :
Orch( tableConnectors)
{
SWSS_LOG_ENTER();

initDefaultHostIntfTable();
initDefaultTrapGroup();
initDefaultTrapIds();
enable_sflow_trap = false;
};

void CoppOrch::initDefaultHostIntfTable()
Expand Down Expand Up @@ -189,6 +191,60 @@ void CoppOrch::getTrapIdList(vector<string> &trap_id_name_list, vector<sai_hosti
}
}

bool CoppOrch::createGenetlinkHostIfTable(vector<string> &trap_id_name_list)
{
SWSS_LOG_ENTER();

vector<sai_hostif_trap_type_t> trap_id_list;

getTrapIdList(trap_id_name_list, trap_id_list);

for (auto trap_id : trap_id_list)
{
auto host_tbl_entry = m_trapid_hostif_table_map.find(trap_id);

if (host_tbl_entry == m_trapid_hostif_table_map.end())
{
sai_object_id_t trap_group_id = m_syncdTrapIds[trap_id].trap_group_obj;
auto hostif_map = m_trap_group_hostif_map.find(trap_group_id);
if (hostif_map != m_trap_group_hostif_map.end())
{
sai_object_id_t hostif_table_entry = SAI_NULL_OBJECT_ID;
sai_attribute_t attr;
vector<sai_attribute_t> sai_host_table_attr;

attr.id = SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE;
attr.value.s32 = SAI_HOSTIF_TABLE_ENTRY_TYPE_TRAP_ID;
sai_host_table_attr.push_back(attr);

attr.id = SAI_HOSTIF_TABLE_ENTRY_ATTR_TRAP_ID;
attr.value.oid = m_syncdTrapIds[trap_id].trap_obj;
sai_host_table_attr.push_back(attr);

attr.id = SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE;
attr.value.s32 = SAI_HOSTIF_TABLE_ENTRY_CHANNEL_TYPE_GENETLINK;
sai_host_table_attr.push_back(attr);

attr.id = SAI_HOSTIF_TABLE_ENTRY_ATTR_HOST_IF;
attr.value.oid = hostif_map->second;
sai_host_table_attr.push_back(attr);

sai_status_t status = sai_hostif_api->create_hostif_table_entry(&hostif_table_entry,
gSwitchId,
(uint32_t)sai_host_table_attr.size(),
sai_host_table_attr.data());
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to create hostif table entry failed, rv %d", status);
return false;
}
m_trapid_hostif_table_map[trap_id] = hostif_table_entry;
}
}
}
return true;
}

bool CoppOrch::applyAttributesToTrapIds(sai_object_id_t trap_group_id,
const vector<sai_hostif_trap_type_t> &trap_id_list,
vector<sai_attribute_t> &trap_id_attribs)
Expand All @@ -211,9 +267,9 @@ bool CoppOrch::applyAttributesToTrapIds(sai_object_id_t trap_group_id,
SWSS_LOG_ERROR("Failed to create trap %d, rv:%d", trap_id, status);
return false;
}
m_syncdTrapIds[trap_id] = trap_group_id;
m_syncdTrapIds[trap_id].trap_group_obj = trap_group_id;
m_syncdTrapIds[trap_id].trap_obj = hostif_trap_id;
}

return true;
}

Expand All @@ -233,6 +289,7 @@ bool CoppOrch::applyTrapIds(sai_object_id_t trap_group, vector<string> &trap_id_
return applyAttributesToTrapIds(trap_group, trap_id_list, trap_id_attribs);
}


bool CoppOrch::removePolicer(string trap_group_name)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -319,6 +376,69 @@ bool CoppOrch::createPolicer(string trap_group_name, vector<sai_attribute_t> &po
return true;
}

bool CoppOrch::createGenetlinkHostIf(string trap_group_name, vector<sai_attribute_t> &genetlink_attribs)
{
SWSS_LOG_ENTER();

sai_object_id_t hostif_id;
sai_status_t sai_status;

sai_status = sai_hostif_api->create_hostif(&hostif_id, gSwitchId,
(uint32_t)genetlink_attribs.size(),
genetlink_attribs.data());
if (sai_status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to create genetlink hostif for trap group %s, rc=%d",
trap_group_name.c_str(), sai_status);
return false;
}

m_trap_group_hostif_map[m_trap_group_map[trap_group_name]] = hostif_id;
return true;
}

bool CoppOrch::removeGenetlinkHostIf(string trap_group_name)
{
SWSS_LOG_ENTER();

sai_status_t sai_status;

for (auto it : m_syncdTrapIds)
{
if (it.second.trap_group_obj == m_trap_group_map[trap_group_name])
{
auto hostTableEntry = m_trapid_hostif_table_map.find(it.first);
if (hostTableEntry != m_trapid_hostif_table_map.end())
{
sai_status = sai_hostif_api->remove_hostif_table_entry(hostTableEntry->second);
if(sai_status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to delete hostif table entry %ld \
on trap group %s. rc=%d", hostTableEntry->second,
trap_group_name.c_str(), sai_status);
return false;
}
m_trapid_hostif_table_map.erase(it.first);
}
}
}

auto hostInfo = m_trap_group_hostif_map.find(m_trap_group_map[trap_group_name]);
if(hostInfo != m_trap_group_hostif_map.end())
{
sai_status = sai_hostif_api->remove_hostif(hostInfo->second);
if(sai_status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to delete host info %ld on trap group %s. rc=%d",
hostInfo->second, trap_group_name.c_str(), sai_status);
return false;
}
m_trap_group_hostif_map.erase(m_trap_group_map[trap_group_name]);
}

return true;
}

task_process_status CoppOrch::processCoppRule(Consumer& consumer)
{
SWSS_LOG_ENTER();
Expand All @@ -334,6 +454,7 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
vector<sai_attribute_t> trap_gr_attribs;
vector<sai_attribute_t> trap_id_attribs;
vector<sai_attribute_t> policer_attribs;
vector<sai_attribute_t> genetlink_attribs;

if (op == SET_COMMAND)
{
Expand All @@ -344,6 +465,14 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
if (fvField(*i) == copp_trap_id_list)
{
trap_id_list = tokenize(fvValue(*i), list_item_delimiter);
auto it = std::find(trap_id_list.begin(), trap_id_list.end(), "sample_packet");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this have other traps in list that must installed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Only sflow can be supported in this trap group

if (it != trap_id_list.end())
{
if (!enable_sflow_trap)
{
return task_process_status::task_need_retry;
}
}
}
else if (fvField(*i) == copp_queue_field)
{
Expand Down Expand Up @@ -441,6 +570,25 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
attr.value.s32 = policer_action;
policer_attribs.push_back(attr);
}
else if (fvField(*i) == copp_genetlink_name)
{
attr.id = SAI_HOSTIF_ATTR_TYPE;
attr.value.s32 = SAI_HOSTIF_TYPE_GENETLINK;
genetlink_attribs.push_back(attr);

attr.id = SAI_HOSTIF_ATTR_NAME;
strncpy(attr.value.chardata, fvValue(*i).c_str(),
sizeof(attr.value.chardata));
genetlink_attribs.push_back(attr);

}
else if (fvField(*i) == copp_genetlink_mcgrp_name)
{
attr.id = SAI_HOSTIF_ATTR_GENETLINK_MCGRP_NAME;
strncpy(attr.value.chardata, fvValue(*i).c_str(),
sizeof(attr.value.chardata));
genetlink_attribs.push_back(attr);
}
else
{
SWSS_LOG_ERROR("Unknown copp field specified:%s\n", fvField(*i).c_str());
Expand Down Expand Up @@ -517,13 +665,29 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
return task_process_status::task_failed;
}
}

if (!genetlink_attribs.empty())
{
if (!createGenetlinkHostIf(trap_group_name, genetlink_attribs))
{
return task_process_status::task_failed;
}
}
}

/* Apply traps to trap group */
if (!applyTrapIds(m_trap_group_map[trap_group_name], trap_id_list, trap_id_attribs))
{
return task_process_status::task_failed;
}

if (!genetlink_attribs.empty())
{
if (!createGenetlinkHostIfTable(trap_id_list))
{
return task_process_status::task_failed;
}
}
}
else if (op == DEL_COMMAND)
{
Expand All @@ -534,6 +698,12 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
return task_process_status::task_failed;
}

if (!removeGenetlinkHostIf(trap_group_name))
{
SWSS_LOG_ERROR("Failed to remove hostif from trap group %s", trap_group_name.c_str());
return task_process_status::task_failed;
}

/* Do not remove default trap group */
if (trap_group_name == default_trap_group)
{
Expand All @@ -545,10 +715,16 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
vector<sai_hostif_trap_type_t> trap_ids_to_reset;
for (auto it : m_syncdTrapIds)
{
if (it.second == m_trap_group_map[trap_group_name])
if (it.second.trap_group_obj == m_trap_group_map[trap_group_name])
{
trap_ids_to_reset.push_back(it.first);
}
sai_status = sai_hostif_api->remove_hostif_trap(it.second.trap_obj);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this new code? I mean it looks generic.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is added to clean up hostif trap during delete case, which was missing in the existing logic

if (sai_status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to remove trap object %ld", it.second.trap_obj);
return task_process_status::task_failed;
}
}

sai_attribute_t attr;
Expand Down Expand Up @@ -586,9 +762,49 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
return task_process_status::task_success;
}

/* Program Sflow trap once we get sflow enable command */
void CoppOrch::coppProcessSflow(Consumer &consumer)
{
auto it = consumer.m_toSync.begin();

while (it != consumer.m_toSync.end())
{
auto tuple = it->second;
string op = kfvOp(tuple);

/*
* Need to handled just 'config sflow enable' command to install the sflow trap group
* for the first time to ensure support of genetlink attributes. Rest of the fields or
* disable value or DEL command are not required to be handled
*
*/
if (op == SET_COMMAND)
{
for (auto i : kfvFieldsValues(tuple))
{
if (fvField(i) == "admin_state")
{
if (fvValue(i) == "enable")
{
enable_sflow_trap = true;
}
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add an else case and log NOTICE stating 'not implemented'

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add comment, since a log will be misleading

it = consumer.m_toSync.erase(it);
}
}

void CoppOrch::doTask(Consumer &consumer)
{
SWSS_LOG_ENTER();
string table_name = consumer.getTableName();

if (table_name == CFG_SFLOW_TABLE_NAME)
{
coppProcessSflow(consumer);
return;
}

if (!gPortsOrch->allPortsReady())
{
Expand Down
31 changes: 27 additions & 4 deletions orchagent/copporch.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,38 @@ const std::string copp_policer_action_green_field = "green_action";
const std::string copp_policer_action_red_field = "red_action";
const std::string copp_policer_action_yellow_field = "yellow_action";

// genetlink fields
const std::string copp_genetlink_name = "genetlink_name";
const std::string copp_genetlink_mcgrp_name = "genetlink_mcgrp_name";

struct copp_trap_objects
{
sai_object_id_t trap_obj;
sai_object_id_t trap_group_obj;
};

/* TrapGroupPolicerTable: trap group ID, policer ID */
typedef std::map<sai_object_id_t, sai_object_id_t> TrapGroupPolicerTable;
/* TrapIdTrapGroupTable: trap ID, trap group ID */
typedef std::map<sai_hostif_trap_type_t, sai_object_id_t> TrapIdTrapGroupTable;
/* TrapIdTrapObjectsTable: trap ID, copp trap objects */
typedef std::map<sai_hostif_trap_type_t, copp_trap_objects> TrapIdTrapObjectsTable;
/* TrapGroupHostIfMap: trap group ID, host interface ID */
typedef std::map<sai_object_id_t, sai_object_id_t> TrapGroupHostIfMap;
/* TrapIdHostIfTableMap: trap type, host table entry ID*/
typedef std::map<sai_hostif_trap_type_t, sai_object_id_t> TrapIdHostIfTableMap;

class CoppOrch : public Orch
{
public:
CoppOrch(swss::DBConnector *db, std::string tableName);
CoppOrch(std::vector<TableConnector> &tableConnectors);
protected:
object_map m_trap_group_map;
bool enable_sflow_trap;

TrapGroupPolicerTable m_trap_group_policer_map;
TrapIdTrapGroupTable m_syncdTrapIds;
TrapIdTrapObjectsTable m_syncdTrapIds;

TrapGroupHostIfMap m_trap_group_hostif_map;
TrapIdHostIfTableMap m_trapid_hostif_table_map;

void initDefaultHostIntfTable();
void initDefaultTrapGroup();
Expand All @@ -54,6 +72,11 @@ class CoppOrch : public Orch

sai_object_id_t getPolicer(std::string trap_group_name);

bool createGenetlinkHostIf(std::string trap_group_name, std::vector<sai_attribute_t> &hostif_attribs);
bool removeGenetlinkHostIf(std::string trap_group_name);
bool createGenetlinkHostIfTable(std::vector<std::string> &trap_id_name_list);
void coppProcessSflow(Consumer& consumer);

virtual void doTask(Consumer& consumer);
};
#endif /* SWSS_COPPORCH_H */
Expand Down
Loading