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

[202012][cherry-pick] Support tunnel traffic QoS remapping #2246

Merged
merged 5 commits into from
Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
67 changes: 64 additions & 3 deletions orchagent/muxorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "aclorch.h"
#include "routeorch.h"
#include "fdborch.h"
#include "qosorch.h"

/* Global variables */
extern Directory<Orch*> gDirectory;
Expand All @@ -32,6 +33,7 @@ extern RouteOrch *gRouteOrch;
extern AclOrch *gAclOrch;
extern PortsOrch *gPortsOrch;
extern FdbOrch *gFdbOrch;
extern QosOrch *gQosOrch;

extern sai_object_id_t gVirtualRouterId;
extern sai_object_id_t gUnderlayIfId;
Expand All @@ -42,7 +44,6 @@ extern sai_next_hop_api_t* sai_next_hop_api;
extern sai_router_interface_api_t* sai_router_intfs_api;

/* Constants */
#define MUX_TUNNEL "MuxTunnel0"
#define MUX_ACL_TABLE_NAME INGRESS_TABLE_DROP
#define MUX_ACL_RULE_NAME "mux_acl_rule"
#define MUX_HW_STATE_UNKNOWN "unknown"
Expand Down Expand Up @@ -162,7 +163,12 @@ static sai_status_t remove_route(IpPrefix &pfx)
return status;
}

static sai_object_id_t create_tunnel(const IpAddress* p_dst_ip, const IpAddress* p_src_ip)
static sai_object_id_t create_tunnel(
const IpAddress* p_dst_ip,
const IpAddress* p_src_ip,
sai_object_id_t tc_to_dscp_map_id,
sai_object_id_t tc_to_queue_map_id,
string dscp_mode_name)
{
sai_status_t status;

Expand Down Expand Up @@ -206,6 +212,22 @@ static sai_object_id_t create_tunnel(const IpAddress* p_dst_ip, const IpAddress*
attr.value.s32 = SAI_TUNNEL_TTL_MODE_PIPE_MODEL;
tunnel_attrs.push_back(attr);

if (dscp_mode_name == "uniform" || dscp_mode_name == "pipe")
{
sai_tunnel_dscp_mode_t dscp_mode;
if (dscp_mode_name == "uniform")
{
dscp_mode = SAI_TUNNEL_DSCP_MODE_UNIFORM_MODEL;
}
else
{
dscp_mode = SAI_TUNNEL_DSCP_MODE_PIPE_MODEL;
}
attr.id = SAI_TUNNEL_ATTR_ENCAP_DSCP_MODE;
attr.value.s32 = dscp_mode;
tunnel_attrs.push_back(attr);
}

attr.id = SAI_TUNNEL_ATTR_LOOPBACK_PACKET_ACTION;
attr.value.s32 = SAI_PACKET_ACTION_DROP;
tunnel_attrs.push_back(attr);
Expand All @@ -224,6 +246,22 @@ static sai_object_id_t create_tunnel(const IpAddress* p_dst_ip, const IpAddress*
tunnel_attrs.push_back(attr);
}

// DSCP rewriting
if (tc_to_dscp_map_id != SAI_NULL_OBJECT_ID)
{
attr.id = SAI_TUNNEL_ATTR_ENCAP_QOS_TC_AND_COLOR_TO_DSCP_MAP;
attr.value.oid = tc_to_dscp_map_id;
tunnel_attrs.push_back(attr);
}

// TC remapping
if (tc_to_queue_map_id != SAI_NULL_OBJECT_ID)
{
attr.id = SAI_TUNNEL_ATTR_ENCAP_QOS_TC_TO_QUEUE_MAP;
attr.value.oid = tc_to_queue_map_id;
tunnel_attrs.push_back(attr);
}

sai_object_id_t tunnel_id;
status = sai_tunnel_api->create_tunnel(&tunnel_id, gSwitchId, (uint32_t)tunnel_attrs.size(), tunnel_attrs.data());
if (status != SAI_STATUS_SUCCESS)
Expand Down Expand Up @@ -1262,7 +1300,30 @@ bool MuxOrch::handlePeerSwitch(const Request& request)

auto it = dst_ips.getIpAddresses().begin();
const IpAddress& dst_ip = *it;
mux_tunnel_id_ = create_tunnel(&peer_ip, &dst_ip);

// Read dscp_mode of MuxTunnel0 from decap_orch
string dscp_mode_name = decap_orch_->getDscpMode(MUX_TUNNEL);
if (dscp_mode_name == "")
{
SWSS_LOG_NOTICE("dscp_mode for tunnel %s is not available. Will not be applied", MUX_TUNNEL);
}

// Read tc_to_dscp_map_id of MuxTunnel0 from decap_orch
sai_object_id_t tc_to_dscp_map_id = SAI_NULL_OBJECT_ID;
decap_orch_->getQosMapId(MUX_TUNNEL, encap_tc_to_dscp_field_name, tc_to_dscp_map_id);
if (tc_to_dscp_map_id == SAI_NULL_OBJECT_ID)
{
SWSS_LOG_NOTICE("tc_to_dscp_map_id for tunnel %s is not available. Will not be applied", MUX_TUNNEL);
}
// Read tc_to_queue_map_id of MuxTunnel0 from decap_orch
sai_object_id_t tc_to_queue_map_id = SAI_NULL_OBJECT_ID;
decap_orch_->getQosMapId(MUX_TUNNEL, encap_tc_to_queue_field_name, tc_to_queue_map_id);
if (tc_to_queue_map_id == SAI_NULL_OBJECT_ID)
{
SWSS_LOG_NOTICE("tc_to_queue_map_id for tunnel %s is not available. Will not be applied", MUX_TUNNEL);
}

mux_tunnel_id_ = create_tunnel(&peer_ip, &dst_ip, tc_to_dscp_map_id, tc_to_queue_map_id, dscp_mode_name);
mux_peer_switch_ = peer_ip;
SWSS_LOG_NOTICE("Mux peer ip '%s' was added, peer name '%s'",
peer_ip.to_string().c_str(), peer_name.c_str());
Expand Down
8 changes: 5 additions & 3 deletions orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ SwitchOrch *gSwitchOrch;
Directory<Orch*> gDirectory;
NatOrch *gNatOrch;
BfdOrch *gBfdOrch;
QosOrch *gQosOrch;

bool gIsNatSupported = false;

Expand Down Expand Up @@ -179,9 +180,10 @@ bool OrchDaemon::init()
CFG_WRED_PROFILE_TABLE_NAME,
CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME,
CFG_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_TABLE_NAME,
CFG_PFC_PRIORITY_TO_QUEUE_MAP_TABLE_NAME
CFG_PFC_PRIORITY_TO_QUEUE_MAP_TABLE_NAME,
CFG_TC_TO_DSCP_MAP_TABLE_NAME
};
QosOrch *qos_orch = new QosOrch(m_configDb, qos_tables);
gQosOrch = new QosOrch(m_configDb, qos_tables);

vector<string> buffer_tables = {
APP_BUFFER_POOL_TABLE_NAME,
Expand Down Expand Up @@ -274,7 +276,7 @@ bool OrchDaemon::init()
* when iterating ConsumerMap. This is ensured implicitly by the order of keys in ordered map.
* For cases when Orch has to process tables in specific order, like PortsOrch during warm start, it has to override Orch::doTask()
*/
m_orchList = { gSwitchOrch, gCrmOrch, gPortsOrch, gBufferOrch, gIntfsOrch, gNeighOrch, gRouteOrch, copp_orch, qos_orch, wm_orch, policer_orch, tunnel_decap_orch, sflow_orch, debug_counter_orch, mux_orch, mux_cb_orch, gBfdOrch};
m_orchList = { gSwitchOrch, gCrmOrch, gPortsOrch, gBufferOrch, gIntfsOrch, gNeighOrch, gRouteOrch, copp_orch, gQosOrch, wm_orch, policer_orch, tunnel_decap_orch, sflow_orch, debug_counter_orch, mux_orch, mux_cb_orch, gBfdOrch};

bool initialize_dtel = false;
if (platform == BFN_PLATFORM_SUBSTRING || platform == VS_PLATFORM_SUBSTRING)
Expand Down
126 changes: 124 additions & 2 deletions orchagent/qosorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,14 @@ type_map QosOrch::m_qos_maps = {
{CFG_QUEUE_TABLE_NAME, new object_reference_map()},
{CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, new object_reference_map()},
{CFG_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_TABLE_NAME, new object_reference_map()},
{CFG_PFC_PRIORITY_TO_QUEUE_MAP_TABLE_NAME, new object_reference_map()}
{CFG_PFC_PRIORITY_TO_QUEUE_MAP_TABLE_NAME, new object_reference_map()},
{CFG_TC_TO_DSCP_MAP_TABLE_NAME, new object_reference_map()},
{APP_TUNNEL_DECAP_TABLE_NAME, new object_reference_map()}
};

#define DSCP_MAX_VAL 63
#define EXP_MAX_VAL 7

task_process_status QosMapHandler::processWorkItem(Consumer& consumer)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -246,7 +251,7 @@ sai_object_id_t DscpToTcMapHandler::addQosItem(const vector<sai_attribute_t> &at
}
SWSS_LOG_DEBUG("created QosMap object:%" PRIx64, sai_object);

applyDscpToTcMapToSwitch(SAI_SWITCH_ATTR_QOS_DSCP_TO_TC_MAP, sai_object);
//applyDscpToTcMapToSwitch(SAI_SWITCH_ATTR_QOS_DSCP_TO_TC_MAP, sai_object);
Copy link
Contributor

Choose a reason for hiding this comment

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

if pcbb is not enabled, we need this function

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. If pcbb is enabled, do we need to set SAI_TUNNEL_ATTR_DECAP_QOS_DSCP_TO_TC_MAP for other IPinIP tunnel except for Mux tunnel?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will merge this PR for now, and fix this issue in another PR.


return sai_object;
}
Expand Down Expand Up @@ -763,6 +768,89 @@ task_process_status QosOrch::handlePfcToQueueTable(Consumer& consumer)
return pfc_to_queue_handler.processWorkItem(consumer);
}

task_process_status QosOrch::handleTcToDscpTable(Consumer& consumer)
{
SWSS_LOG_ENTER();
TcToDscpMapHandler tc_to_dscp_handler;
return tc_to_dscp_handler.processWorkItem(consumer);
}

bool TcToDscpMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple,
vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();

sai_attribute_t list_attr;
list_attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST;
list_attr.value.qosmap.count = (uint32_t)kfvFieldsValues(tuple).size();
list_attr.value.qosmap.list = new sai_qos_map_t[list_attr.value.qosmap.count]();
uint32_t ind = 0;

for (auto i = kfvFieldsValues(tuple).begin(); i != kfvFieldsValues(tuple).end(); i++, ind++)
{
try
{
auto value = stoi(fvValue(*i));
if (value < 0)
{
SWSS_LOG_ERROR("DSCP value %d is negative", value);
delete[] list_attr.value.qosmap.list;
return false;
}
else if (value > DSCP_MAX_VAL)
{
SWSS_LOG_ERROR("DSCP value %d is greater than max value %d", value, DSCP_MAX_VAL);
delete[] list_attr.value.qosmap.list;
return false;
}
list_attr.value.qosmap.list[ind].key.tc = static_cast<sai_uint8_t>(stoi(fvField(*i)));
list_attr.value.qosmap.list[ind].value.dscp = static_cast<sai_uint8_t>(value);

SWSS_LOG_DEBUG("key.tc:%d, value.dscp:%d",
list_attr.value.qosmap.list[ind].key.tc,
list_attr.value.qosmap.list[ind].value.dscp);
}
catch(const invalid_argument& e)
{
SWSS_LOG_ERROR("Got exception during conversion: %s", e.what());
delete[] list_attr.value.qosmap.list;
return false;
}
}
attributes.push_back(list_attr);
return true;
}

sai_object_id_t TcToDscpMapHandler::addQosItem(const vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
sai_status_t sai_status;
sai_object_id_t sai_object;
vector<sai_attribute_t> qos_map_attrs;

sai_attribute_t qos_map_attr;
qos_map_attr.id = SAI_QOS_MAP_ATTR_TYPE;
qos_map_attr.value.u32 = SAI_QOS_MAP_TYPE_TC_AND_COLOR_TO_DSCP;
qos_map_attrs.push_back(qos_map_attr);

qos_map_attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST;
qos_map_attr.value.qosmap.count = attributes[0].value.qosmap.count;
qos_map_attr.value.qosmap.list = attributes[0].value.qosmap.list;
qos_map_attrs.push_back(qos_map_attr);

sai_status = sai_qos_map_api->create_qos_map(&sai_object,
gSwitchId,
(uint32_t)qos_map_attrs.size(),
qos_map_attrs.data());
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to create tc_to_dscp map. status:%d", sai_status);
return SAI_NULL_OBJECT_ID;
}
SWSS_LOG_DEBUG("created QosMap object:%" PRIx64, sai_object);
return sai_object;
}

QosOrch::QosOrch(DBConnector *db, vector<string> &tableNames) : Orch(db, tableNames)
{
SWSS_LOG_ENTER();
Expand All @@ -786,6 +874,7 @@ void QosOrch::initTableHandlers()
m_qos_handler_map.insert(qos_handler_pair(CFG_QUEUE_TABLE_NAME, &QosOrch::handleQueueTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_PORT_QOS_MAP_TABLE_NAME, &QosOrch::handlePortQosMapTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_WRED_PROFILE_TABLE_NAME, &QosOrch::handleWredProfileTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_TC_TO_DSCP_MAP_TABLE_NAME, &QosOrch::handleTcToDscpTable));

m_qos_handler_map.insert(qos_handler_pair(CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, &QosOrch::handleTcToPgTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_TABLE_NAME, &QosOrch::handlePfcPrioToPgTable));
Expand Down Expand Up @@ -1509,3 +1598,36 @@ void QosOrch::doTask(Consumer &consumer)
}
}
}


/**
* Function Description:
* @brief Resolve the id of QoS map that is referenced by tunnel
*
* Arguments:
* @param[in] referencing_table_name - The name of table that is referencing the QoS map
* @param[in] tunnle_name - The name of tunnel
* @param[in] map_type_name - The type of referenced QoS map
* @param[in] tuple - The KeyOpFieldsValuesTuple that contains keys - values
*
* Return Values:
* @return The sai_object_id of referenced map, or SAI_NULL_OBJECT_ID if there's an error
*/
sai_object_id_t QosOrch::resolveTunnelQosMap(std::string referencing_table_name, std::string tunnel_name, std::string map_type_name, KeyOpFieldsValuesTuple& tuple)
{
sai_object_id_t id;
string object_name;
ref_resolve_status status = resolveFieldRefValue(m_qos_maps, map_type_name, tuple, id, object_name);
if (status == ref_resolve_status::success)
{

setObjectReference(m_qos_maps, referencing_table_name, tunnel_name, map_type_name, object_name);
SWSS_LOG_INFO("Resolved QoS map for table %s tunnel %s type %s name %s", referencing_table_name.c_str(), tunnel_name.c_str(), map_type_name.c_str(), object_name.c_str());
return id;
}
else
{
SWSS_LOG_ERROR("Failed to resolve QoS map for table %s tunnel %s type %s", referencing_table_name.c_str(), tunnel_name.c_str(), map_type_name.c_str());
return SAI_NULL_OBJECT_ID;
}
}
16 changes: 16 additions & 0 deletions orchagent/qosorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const string green_min_threshold_field_name = "green_min_threshold";
const string red_drop_probability_field_name = "red_drop_probability";
const string yellow_drop_probability_field_name = "yellow_drop_probability";
const string green_drop_probability_field_name = "green_drop_probability";
const string decap_dscp_to_tc_field_name = "decap_dscp_to_tc_map";
const string decap_tc_to_pg_field_name = "decap_tc_to_pg_map";
const string encap_tc_to_queue_field_name = "encap_tc_to_queue_map";
const string encap_tc_to_dscp_field_name = "encap_tc_to_dscp_map";

const string wred_profile_field_name = "wred_profile";
const string wred_red_enable_field_name = "wred_red_enable";
Expand Down Expand Up @@ -122,13 +126,24 @@ class PfcToQueueHandler : public QosMapHandler
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes);
};

// Handler for TC_TO_DSCP_MAP
class TcToDscpMapHandler : public QosMapHandler
{
public:
bool convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes) override;
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes) override;
};

class QosOrch : public Orch
{
public:
QosOrch(DBConnector *db, vector<string> &tableNames);

static type_map& getTypeMap();
static type_map m_qos_maps;

sai_object_id_t resolveTunnelQosMap(std::string referencing_table_name, std::string tunnel_name, std::string map_type_name, KeyOpFieldsValuesTuple& tuple);

private:
void doTask() override;
virtual void doTask(Consumer& consumer);
Expand All @@ -149,6 +164,7 @@ class QosOrch : public Orch
task_process_status handleSchedulerTable(Consumer& consumer);
task_process_status handleQueueTable(Consumer& consumer);
task_process_status handleWredProfileTable(Consumer& consumer);
task_process_status handleTcToDscpTable(Consumer& consumer);

sai_object_id_t getSchedulerGroup(const Port &port, const sai_object_id_t queue_id);

Expand Down
Loading