From 2d3f0d03d3279756fbe13c92e0042c4e055e5ad1 Mon Sep 17 00:00:00 2001 From: Rakesh Datta Date: Tue, 16 Jul 2019 16:08:59 -0700 Subject: [PATCH 1/3] * Update: For sflow feature, 'tc' command is to be invoked while sampling is configured on a port. This is applicable only for sflow feature running on sonic VS. Signed-off-by: Rakesh Datta --- vslib/inc/sai_vs.h | 1 + vslib/inc/sai_vs_state.h | 25 ++++++- vslib/src/sai_vs_hostintf.cpp | 1 + vslib/src/sai_vs_port.cpp | 118 +++++++++++++++++++++++++++++++++- vslib/src/sai_vs_switch.cpp | 4 ++ 5 files changed, 147 insertions(+), 2 deletions(-) diff --git a/vslib/inc/sai_vs.h b/vslib/inc/sai_vs.h index ef9578822..05e28237a 100644 --- a/vslib/inc/sai_vs.h +++ b/vslib/inc/sai_vs.h @@ -86,6 +86,7 @@ typedef enum _sai_vs_switch_type_t } sai_vs_switch_type_t; +extern sai_object_id_t g_vs_switch_id; extern bool g_vs_hostif_use_tap_device; extern sai_vs_switch_type_t g_vs_switch_type; extern std::recursive_mutex g_recursive_mutex; diff --git a/vslib/inc/sai_vs_state.h b/vslib/inc/sai_vs_state.h index e62668e60..039e58fd0 100644 --- a/vslib/inc/sai_vs_state.h +++ b/vslib/inc/sai_vs_state.h @@ -253,11 +253,34 @@ class SwitchState return it->second; } + void setTapNameToPortId( + _In_ const std::string& tapname, + _In_ sai_object_id_t port_id) + { + SWSS_LOG_ENTER(); + + m_port_id_to_tapname[port_id] = tapname; + } + + bool getTapNameFromPortId( + _In_ const sai_object_id_t port_id, + _Out_ std::string& if_name) + { + SWSS_LOG_ENTER(); + + if (m_port_id_to_tapname.find(port_id) != m_port_id_to_tapname.end()) + { + if_name = m_port_id_to_tapname[port_id]; + return true; + } + return false; + } + private: sai_object_id_t m_switch_id; - std::map m_ifname_to_port_id; + std::map m_port_id_to_tapname; swss::SelectableEvent m_link_thread_event; diff --git a/vslib/src/sai_vs_hostintf.cpp b/vslib/src/sai_vs_hostintf.cpp index b43dd19ea..8a491c4b4 100644 --- a/vslib/src/sai_vs_hostintf.cpp +++ b/vslib/src/sai_vs_hostintf.cpp @@ -1235,6 +1235,7 @@ sai_status_t vs_create_hostif_tap_interface( g_switch_state_map.at(switch_id)->setIfNameToPortId(vname, obj_id); + g_switch_state_map.at(switch_id)->setTapNameToPortId(name, obj_id); // TODO what about FDB entries notifications, they also should // be generated if new mac address will show up on the interface/arp table diff --git a/vslib/src/sai_vs_port.cpp b/vslib/src/sai_vs_port.cpp index 2c599082d..010d7447d 100644 --- a/vslib/src/sai_vs_port.cpp +++ b/vslib/src/sai_vs_port.cpp @@ -39,8 +39,124 @@ sai_status_t vs_create_port( return SAI_STATUS_SUCCESS; } +sai_status_t vs_set_port_attribute( + _In_ sai_object_id_t port_id, + _In_ const sai_attribute_t *attr) +{ + MUTEX(); + SWSS_LOG_ENTER(); + + std::string cmd; + + // For samplepacket attr, 'tc sample' command is invoked + if (attr->id == SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE) + { + // Get the samplepacket object id + sai_object_id_t samplepacket_oid = attr->value.oid; + + // Get the if_name from the port_id + std::string if_name; + if (g_vs_switch_id == SAI_NULL_OBJECT_ID) + { + SWSS_LOG_ERROR("g_vs_switch_id is null"); + return SAI_STATUS_FAILURE; + } + + auto it = g_switch_state_map.find(g_vs_switch_id); + if (it == g_switch_state_map.end()) + { + SWSS_LOG_ERROR("No switch state found for the switch id %s", + sai_serialize_object_id(g_vs_switch_id).c_str()); + return SAI_STATUS_FAILURE; + } + + auto sw = it->second; + if (sw == nullptr) + { + SWSS_LOG_ERROR("switch state for the switch id %s is null", + sai_serialize_object_id(g_vs_switch_id).c_str()); + return SAI_STATUS_FAILURE; + } + + if (sw->getTapNameFromPortId(port_id, if_name) == false) + { + SWSS_LOG_ERROR("tap interface name corresponding to the port id %s is not found", + sai_serialize_object_id(port_id).c_str()); + return SAI_STATUS_FAILURE; + } + + if (samplepacket_oid == SAI_NULL_OBJECT_ID) + { + //Delete the sampling session + cmd.assign("tc qdisc delete dev " + if_name + " handle ffff: ingress"); + if (system(cmd.c_str()) == -1) + { + SWSS_LOG_ERROR("unable to delete the sampling session \ + for the interface %s",if_name); + SWSS_LOG_ERROR("failed to apply the command: %s",cmd); + return SAI_STATUS_FAILURE; + } + SWSS_LOG_INFO("successfully applied the command: %s", cmd); + } else { + //Get the sample rate from the sample object + sai_attribute_t samplepacket_attr; + samplepacket_attr.id = SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE; + + if (SAI_STATUS_SUCCESS == \ + vs_generic_get(SAI_OBJECT_TYPE_SAMPLEPACKET, samplepacket_oid, 1, &samplepacket_attr)) + { + int rate = samplepacket_attr.value.u32; + + //Set the default sample group ID + std::string group("1"); + + //Check if sampling is already enabled on the port + //If yes, the session would not be re-created + sai_attribute_t port_attr; + port_attr.id = SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE; + + if ((vs_generic_get(SAI_OBJECT_TYPE_PORT, port_id, 1, &port_attr) \ + == SAI_STATUS_SUCCESS) && (port_attr.value.oid != SAI_NULL_OBJECT_ID)) + { + //Sampling session is already created + SWSS_LOG_INFO("sampling is already enabled on the port: %s", \ + sai_serialize_object_id(port_id).c_str()); + } else { + //Create a new sampling session + cmd.assign("tc qdisc add dev " + if_name + " handle ffff: ingress"); + if (system(cmd.c_str()) == -1) + { + SWSS_LOG_ERROR("unable to create a sampling session for the interface %s", if_name); + SWSS_LOG_ERROR("failed to apply the command: %s",cmd); + return SAI_STATUS_FAILURE; + } + SWSS_LOG_INFO("successfully applied the command: %s", cmd); + } + + //Set the sampling rate of the port + cmd.assign("tc filter add dev " + if_name + \ + " parent ffff: matchall action sample rate " + std::to_string(rate) + \ + " group " + group); + if (system(cmd.c_str()) == -1) + { + SWSS_LOG_ERROR("unable to update the sampling rate of the interface %s",if_name); + SWSS_LOG_ERROR("failed to apply the command: %s",cmd); + return SAI_STATUS_FAILURE; + } + SWSS_LOG_INFO("successfully applied the command: %s", cmd); + } else { + SWSS_LOG_ERROR("failed to update the port %s, unable to read the sample attr", if_name); + return SAI_STATUS_FAILURE; + } + } + SWSS_LOG_INFO("successfully modified the sampling config of the port: %s", + sai_serialize_object_id(port_id).c_str()); + } + + return meta_sai_set_oid((sai_object_type_t)SAI_OBJECT_TYPE_PORT, port_id, attr, &vs_generic_set); +} + VS_REMOVE(PORT,port); -VS_SET(PORT,port); VS_GET(PORT,port); VS_GENERIC_QUAD(PORT_POOL,port_pool); VS_GENERIC_STATS(PORT,port); diff --git a/vslib/src/sai_vs_switch.cpp b/vslib/src/sai_vs_switch.cpp index ae2204e30..404f1a4ea 100644 --- a/vslib/src/sai_vs_switch.cpp +++ b/vslib/src/sai_vs_switch.cpp @@ -14,6 +14,8 @@ #include +sai_object_id_t g_vs_switch_id = SAI_NULL_OBJECT_ID; + /** * @brief Get SwitchState by switch id. * @@ -306,6 +308,8 @@ sai_status_t vs_create_switch( vs_create_netlink_message_listener(*switch_id); } + g_vs_switch_id = *switch_id; + return status; } From 3f38ee583dc9bb13693ee8eaf546b48957cca709 Mon Sep 17 00:00:00 2001 From: Rakesh Datta Date: Wed, 31 Jul 2019 13:54:04 -0700 Subject: [PATCH 2/3] Correct the spell check error * Update: modified some words to pass the spell-check error Signed-off-by: Rakesh Datta --- vslib/src/sai_vs_port.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vslib/src/sai_vs_port.cpp b/vslib/src/sai_vs_port.cpp index 010d7447d..f0a6a9f91 100644 --- a/vslib/src/sai_vs_port.cpp +++ b/vslib/src/sai_vs_port.cpp @@ -48,13 +48,13 @@ sai_status_t vs_set_port_attribute( std::string cmd; - // For samplepacket attr, 'tc sample' command is invoked + // Special handling for the sampling attribute modification if (attr->id == SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE) { - // Get the samplepacket object id + // Get the sample-packet object id sai_object_id_t samplepacket_oid = attr->value.oid; - // Get the if_name from the port_id + // Get the interface name from the port id std::string if_name; if (g_vs_switch_id == SAI_NULL_OBJECT_ID) { From 8a96ebfa25fc980abbd36fe202b05a08ce559294 Mon Sep 17 00:00:00 2001 From: Rakesh Datta Date: Wed, 14 Aug 2019 13:33:50 -0700 Subject: [PATCH 3/3] * Update: replace global switch_id with the API sai_switch_id_query() * Bugfix: Updation of sampling rate is creating multiple 'tc filter' entries Signed-off-by: Rakesh Datta --- vslib/inc/sai_vs.h | 1 - vslib/src/sai_vs_port.cpp | 40 +++++++++++++++++++++++++------------ vslib/src/sai_vs_switch.cpp | 4 ---- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/vslib/inc/sai_vs.h b/vslib/inc/sai_vs.h index 05e28237a..ef9578822 100644 --- a/vslib/inc/sai_vs.h +++ b/vslib/inc/sai_vs.h @@ -86,7 +86,6 @@ typedef enum _sai_vs_switch_type_t } sai_vs_switch_type_t; -extern sai_object_id_t g_vs_switch_id; extern bool g_vs_hostif_use_tap_device; extern sai_vs_switch_type_t g_vs_switch_type; extern std::recursive_mutex g_recursive_mutex; diff --git a/vslib/src/sai_vs_port.cpp b/vslib/src/sai_vs_port.cpp index f0a6a9f91..f5824d1b1 100644 --- a/vslib/src/sai_vs_port.cpp +++ b/vslib/src/sai_vs_port.cpp @@ -56,17 +56,19 @@ sai_status_t vs_set_port_attribute( // Get the interface name from the port id std::string if_name; - if (g_vs_switch_id == SAI_NULL_OBJECT_ID) + + sai_object_id_t vs_switch_id = sai_switch_id_query(port_id); + if (vs_switch_id == SAI_NULL_OBJECT_ID) { - SWSS_LOG_ERROR("g_vs_switch_id is null"); + SWSS_LOG_ERROR("vs_switch_id is null"); return SAI_STATUS_FAILURE; } - auto it = g_switch_state_map.find(g_vs_switch_id); + auto it = g_switch_state_map.find(vs_switch_id); if (it == g_switch_state_map.end()) { SWSS_LOG_ERROR("No switch state found for the switch id %s", - sai_serialize_object_id(g_vs_switch_id).c_str()); + sai_serialize_object_id(vs_switch_id).c_str()); return SAI_STATUS_FAILURE; } @@ -74,7 +76,7 @@ sai_status_t vs_set_port_attribute( if (sw == nullptr) { SWSS_LOG_ERROR("switch state for the switch id %s is null", - sai_serialize_object_id(g_vs_switch_id).c_str()); + sai_serialize_object_id(vs_switch_id).c_str()); return SAI_STATUS_FAILURE; } @@ -111,28 +113,40 @@ sai_status_t vs_set_port_attribute( std::string group("1"); //Check if sampling is already enabled on the port - //If yes, the session would not be re-created sai_attribute_t port_attr; port_attr.id = SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE; + // When the sampling parameters are updated, + // a delete and add operation is performed on the sampling session. + // If the sampling session is already created, it is deleted below. if ((vs_generic_get(SAI_OBJECT_TYPE_PORT, port_id, 1, &port_attr) \ == SAI_STATUS_SUCCESS) && (port_attr.value.oid != SAI_NULL_OBJECT_ID)) { //Sampling session is already created - SWSS_LOG_INFO("sampling is already enabled on the port: %s", \ + SWSS_LOG_INFO("sampling is already enabled on the port: %s .. Deleting it", \ sai_serialize_object_id(port_id).c_str()); - } else { - //Create a new sampling session - cmd.assign("tc qdisc add dev " + if_name + " handle ffff: ingress"); - if (system(cmd.c_str()) == -1) - { - SWSS_LOG_ERROR("unable to create a sampling session for the interface %s", if_name); + + //Delete the sampling session + cmd.assign("tc qdisc delete dev " + if_name + " handle ffff: ingress"); + if (system(cmd.c_str()) == -1){ + SWSS_LOG_ERROR("unable to delete the sampling session \ + for the interface %s",if_name); SWSS_LOG_ERROR("failed to apply the command: %s",cmd); return SAI_STATUS_FAILURE; } SWSS_LOG_INFO("successfully applied the command: %s", cmd); } + //Create a new sampling session + cmd.assign("tc qdisc add dev " + if_name + " handle ffff: ingress"); + if (system(cmd.c_str()) == -1) + { + SWSS_LOG_ERROR("unable to create a sampling session for the interface %s", if_name); + SWSS_LOG_ERROR("failed to apply the command: %s",cmd); + return SAI_STATUS_FAILURE; + } + SWSS_LOG_INFO("successfully applied the command: %s", cmd); + //Set the sampling rate of the port cmd.assign("tc filter add dev " + if_name + \ " parent ffff: matchall action sample rate " + std::to_string(rate) + \ diff --git a/vslib/src/sai_vs_switch.cpp b/vslib/src/sai_vs_switch.cpp index 404f1a4ea..ae2204e30 100644 --- a/vslib/src/sai_vs_switch.cpp +++ b/vslib/src/sai_vs_switch.cpp @@ -14,8 +14,6 @@ #include -sai_object_id_t g_vs_switch_id = SAI_NULL_OBJECT_ID; - /** * @brief Get SwitchState by switch id. * @@ -308,8 +306,6 @@ sai_status_t vs_create_switch( vs_create_netlink_message_listener(*switch_id); } - g_vs_switch_id = *switch_id; - return status; }