From 6ea4ea351fa78cea6e2390a4f2211d9ddca0187c Mon Sep 17 00:00:00 2001 From: Wenda Ni Date: Sat, 18 Aug 2018 12:12:19 -0700 Subject: [PATCH] Expose wred drop probability configurability & Support ecn on/off on a queue (#584) * Expose the capability to config wred drop probability (#571) * Add the capability to set wred drop probability of all packet colors (green, yellow, and red) Signed-off-by: Wenda * Ensure drop probability takes default value 100% if not explicitly specified in qos.json Signed-off-by: Wenda * Use "[WRED_PROFILE|]" as a CLI signal to unbind wred profile from a queue or a list of queues; Add the parsing and processing logic in qosorch to support such an operation Signed-off-by: Wenda * Add print out for debugging purpose modified: orchagent/qosorch.cpp * Adjust log level Signed-off-by: Wenda * Change to use "[]" as a signal to unbind wred profile from a queue or a list of queues Signed-off-by: Wenda * Remove logs for debugging * Adjust code format * Address comments Signed-off-by: Wenda --- orchagent/orch.cpp | 22 ++++++++++- orchagent/orch.h | 1 + orchagent/qosorch.cpp | 88 +++++++++++++++++++++++++++++++++++++------ orchagent/qosorch.h | 73 ++++++++++++++++++----------------- 4 files changed, 136 insertions(+), 48 deletions(-) diff --git a/orchagent/orch.cpp b/orchagent/orch.cpp index 235b4661d1..cb65825b34 100644 --- a/orchagent/orch.cpp +++ b/orchagent/orch.cpp @@ -137,13 +137,18 @@ void Consumer::drain() - Validates reference has proper format which is [table_name:object_name] - validates table_name exists - validates object with object_name exists + +- Special case: +- Deem reference format [] as valid, and return true. But in such a case, +- both type_name and object_name are cleared to empty strings as an +- indication to the caller of the special case */ bool Orch::parseReference(type_map &type_maps, string &ref_in, string &type_name, string &object_name) { SWSS_LOG_ENTER(); SWSS_LOG_DEBUG("input:%s", ref_in.c_str()); - if (ref_in.size() < 3) + if (ref_in.size() < 2) { SWSS_LOG_ERROR("invalid reference received:%s\n", ref_in.c_str()); return false; @@ -153,6 +158,17 @@ bool Orch::parseReference(type_map &type_maps, string &ref_in, string &type_name SWSS_LOG_ERROR("malformed reference:%s. Must be surrounded by [ ]\n", ref_in.c_str()); return false; } + if (ref_in.size() == 2) + { + // value set by user is "[]" + // Deem it as a valid format + // clear both type_name and object_name + // as an indication to the caller that + // such a case has been encountered + type_name.clear(); + object_name.clear(); + return true; + } string ref_content = ref_in.substr(1, ref_in.size() - 2); vector tokens; tokens = tokenize(ref_content, delimiter); @@ -208,6 +224,10 @@ ref_resolve_status Orch::resolveFieldRefValue( { return ref_resolve_status::not_resolved; } + else if (ref_type_name.empty() && object_name.empty()) + { + return ref_resolve_status::empty; + } sai_object = (*(type_maps[ref_type_name]))[object_name]; hit = true; } diff --git a/orchagent/orch.h b/orchagent/orch.h index eddece4081..fb3d9b0048 100644 --- a/orchagent/orch.h +++ b/orchagent/orch.h @@ -130,6 +130,7 @@ typedef enum field_not_found, multiple_instances, not_resolved, + empty, failure } ref_resolve_status; diff --git a/orchagent/qosorch.cpp b/orchagent/qosorch.cpp index 23f0e9f0c9..e4c5c96d16 100644 --- a/orchagent/qosorch.cpp +++ b/orchagent/qosorch.cpp @@ -34,6 +34,12 @@ map ecn_map = { {"ecn_all", SAI_ECN_MARK_MODE_ALL} }; +enum { + GREEN_DROP_PROBABILITY_SET = (1U << 0), + YELLOW_DROP_PROBABILITY_SET = (1U << 1), + RED_DROP_PROBABILITY_SET = (1U << 2) +}; + map qos_to_attr_map = { {dscp_to_tc_field_name, SAI_PORT_ATTR_QOS_DSCP_TO_TC_MAP}, {tc_to_queue_field_name, SAI_PORT_ATTR_QOS_TC_TO_QUEUE_MAP}, @@ -329,6 +335,24 @@ bool WredMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tupl attr.value.s32 = stoi(fvValue(*i)); attribs.push_back(attr); } + else if (fvField(*i) == green_drop_probability_field_name) + { + attr.id = SAI_WRED_ATTR_GREEN_DROP_PROBABILITY; + attr.value.s32 = stoi(fvValue(*i)); + attribs.push_back(attr); + } + else if (fvField(*i) == yellow_drop_probability_field_name) + { + attr.id = SAI_WRED_ATTR_YELLOW_DROP_PROBABILITY; + attr.value.s32 = stoi(fvValue(*i)); + attribs.push_back(attr); + } + else if (fvField(*i) == red_drop_probability_field_name) + { + attr.id = SAI_WRED_ATTR_RED_DROP_PROBABILITY; + attr.value.s32 = stoi(fvValue(*i)); + attribs.push_back(attr); + } else if (fvField(*i) == wred_green_enable_field_name) { attr.id = SAI_WRED_ATTR_GREEN_ENABLE; @@ -394,14 +418,7 @@ sai_object_id_t WredMapHandler::addQosItem(const vector &attrib sai_object_id_t sai_object; sai_attribute_t attr; vector attrs; - - attr.id = SAI_WRED_ATTR_GREEN_DROP_PROBABILITY; - attr.value.s32 = 100; - attrs.push_back(attr); - - attr.id = SAI_WRED_ATTR_YELLOW_DROP_PROBABILITY; - attr.value.s32 = 100; - attrs.push_back(attr); + uint8_t drop_prob_set = 0; attr.id = SAI_WRED_ATTR_WEIGHT; attr.value.s32 = 0; @@ -410,7 +427,39 @@ sai_object_id_t WredMapHandler::addQosItem(const vector &attrib for(auto attrib : attribs) { attrs.push_back(attrib); + + if (attrib.id == SAI_WRED_ATTR_GREEN_DROP_PROBABILITY) + { + drop_prob_set |= GREEN_DROP_PROBABILITY_SET; + } + else if (attrib.id == SAI_WRED_ATTR_YELLOW_DROP_PROBABILITY) + { + drop_prob_set |= YELLOW_DROP_PROBABILITY_SET; + } + else if (attrib.id == SAI_WRED_ATTR_RED_DROP_PROBABILITY) + { + drop_prob_set |= RED_DROP_PROBABILITY_SET; + } + } + if (!(drop_prob_set & GREEN_DROP_PROBABILITY_SET)) + { + attr.id = SAI_WRED_ATTR_GREEN_DROP_PROBABILITY; + attr.value.s32 = 100; + attrs.push_back(attr); + } + if (!(drop_prob_set & YELLOW_DROP_PROBABILITY_SET)) + { + attr.id = SAI_WRED_ATTR_YELLOW_DROP_PROBABILITY; + attr.value.s32 = 100; + attrs.push_back(attr); + } + if (!(drop_prob_set & RED_DROP_PROBABILITY_SET)) + { + attr.id = SAI_WRED_ATTR_RED_DROP_PROBABILITY; + attr.value.s32 = 100; + attrs.push_back(attr); } + sai_status = sai_wred_api->create_wred(&sai_object, gSwitchId, (uint32_t)attrs.size(), attrs.data()); if (sai_status != SAI_STATUS_SUCCESS) { @@ -1133,13 +1182,28 @@ task_process_status QosOrch::handleQueueTable(Consumer& consumer) } else if (resolve_result != ref_resolve_status::field_not_found) { - if(ref_resolve_status::not_resolved == resolve_result) + if (ref_resolve_status::empty == resolve_result) + { + SWSS_LOG_INFO("Missing wred reference. Unbind wred profile from queue"); + // NOTE: The wred profile is un-bound from the port. But the wred profile itself still exists + // and stays untouched. + result = applyWredProfileToQueue(port, queue_ind, SAI_NULL_OBJECT_ID); + if (!result) + { + SWSS_LOG_ERROR("Failed unbinding field:%s from port:%s, queue:%zd, line:%d", wred_profile_field_name.c_str(), port.m_alias.c_str(), queue_ind, __LINE__); + return task_process_status::task_failed; + } + } + else if (ref_resolve_status::not_resolved == resolve_result) { - SWSS_LOG_INFO("Missing or invalid wred reference"); + SWSS_LOG_INFO("Invalid wred reference"); return task_process_status::task_need_retry; } - SWSS_LOG_ERROR("Resolving wred reference failed"); - return task_process_status::task_failed; + else + { + SWSS_LOG_ERROR("Resolving wred reference failed"); + return task_process_status::task_failed; + } } } } diff --git a/orchagent/qosorch.h b/orchagent/qosorch.h index 03b70a7dbc..0d9d22cd35 100644 --- a/orchagent/qosorch.h +++ b/orchagent/qosorch.h @@ -7,41 +7,44 @@ #include "orch.h" #include "portsorch.h" -const string dscp_to_tc_field_name = "dscp_to_tc_map"; -const string pfc_to_pg_map_name = "pfc_to_pg_map"; -const string pfc_to_queue_map_name = "pfc_to_queue_map"; -const string pfc_enable_name = "pfc_enable"; -const string tc_to_pg_map_field_name = "tc_to_pg_map"; -const string tc_to_queue_field_name = "tc_to_queue_map"; -const string scheduler_field_name = "scheduler"; -const string red_max_threshold_field_name = "red_max_threshold"; -const string red_min_threshold_field_name = "red_min_threshold"; -const string yellow_max_threshold_field_name = "yellow_max_threshold"; -const string yellow_min_threshold_field_name = "yellow_min_threshold"; -const string green_max_threshold_field_name = "green_max_threshold"; -const string green_min_threshold_field_name = "green_min_threshold"; - -const string wred_profile_field_name = "wred_profile"; -const string wred_red_enable_field_name = "wred_red_enable"; -const string wred_yellow_enable_field_name = "wred_yellow_enable"; -const string wred_green_enable_field_name = "wred_green_enable"; - -const string scheduler_algo_type_field_name = "type"; -const string scheduler_algo_DWRR = "DWRR"; -const string scheduler_algo_WRR = "WRR"; -const string scheduler_algo_STRICT = "STRICT"; -const string scheduler_weight_field_name = "weight"; -const string scheduler_priority_field_name = "priority"; - -const string ecn_field_name = "ecn"; -const string ecn_none = "ecn_none"; -const string ecn_red = "ecn_red"; -const string ecn_yellow = "ecn_yellow"; -const string ecn_yellow_red = "ecn_yellow_red"; -const string ecn_green = "ecn_green"; -const string ecn_green_red = "ecn_green_red"; -const string ecn_green_yellow = "ecn_green_yellow"; -const string ecn_all = "ecn_all"; +const string dscp_to_tc_field_name = "dscp_to_tc_map"; +const string pfc_to_pg_map_name = "pfc_to_pg_map"; +const string pfc_to_queue_map_name = "pfc_to_queue_map"; +const string pfc_enable_name = "pfc_enable"; +const string tc_to_pg_map_field_name = "tc_to_pg_map"; +const string tc_to_queue_field_name = "tc_to_queue_map"; +const string scheduler_field_name = "scheduler"; +const string red_max_threshold_field_name = "red_max_threshold"; +const string red_min_threshold_field_name = "red_min_threshold"; +const string yellow_max_threshold_field_name = "yellow_max_threshold"; +const string yellow_min_threshold_field_name = "yellow_min_threshold"; +const string green_max_threshold_field_name = "green_max_threshold"; +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 wred_profile_field_name = "wred_profile"; +const string wred_red_enable_field_name = "wred_red_enable"; +const string wred_yellow_enable_field_name = "wred_yellow_enable"; +const string wred_green_enable_field_name = "wred_green_enable"; + +const string scheduler_algo_type_field_name = "type"; +const string scheduler_algo_DWRR = "DWRR"; +const string scheduler_algo_WRR = "WRR"; +const string scheduler_algo_STRICT = "STRICT"; +const string scheduler_weight_field_name = "weight"; +const string scheduler_priority_field_name = "priority"; + +const string ecn_field_name = "ecn"; +const string ecn_none = "ecn_none"; +const string ecn_red = "ecn_red"; +const string ecn_yellow = "ecn_yellow"; +const string ecn_yellow_red = "ecn_yellow_red"; +const string ecn_green = "ecn_green"; +const string ecn_green_red = "ecn_green_red"; +const string ecn_green_yellow = "ecn_green_yellow"; +const string ecn_all = "ecn_all"; class QosMapHandler {