Skip to content

Commit

Permalink
[202012][cherry-pick] Support tunnel traffic QoS remapping (#2246)
Browse files Browse the repository at this point in the history
Support tunnel traffic QoS remapping

* Support tunnel traffic QoS remapping

Signed-off-by: bingwang <bingwang@microsoft.com>
  • Loading branch information
bingwang-ms committed Jun 1, 2022
1 parent 903d594 commit ab675b3
Show file tree
Hide file tree
Showing 8 changed files with 716 additions and 84 deletions.
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);

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

0 comments on commit ab675b3

Please sign in to comment.