From c91a7f27150b653bc0de3badb4a87676800ca490 Mon Sep 17 00:00:00 2001 From: Andriy Yurkiv <70649192+ayurkiv-nvda@users.noreply.github.com> Date: Fri, 5 Nov 2021 23:22:13 +0200 Subject: [PATCH] [switchorch] Implement VXLAN src port range feature (#1959) * Implement VXLAN src port range feature configuring Signed-off-by: Andriy Yurkiv --- orchagent/switchorch.cpp | 81 ++++++++++++++++++++++++++++++++++++++-- orchagent/switchorch.h | 3 ++ tests/test_switch.py | 13 ++++--- 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/orchagent/switchorch.cpp b/orchagent/switchorch.cpp index 77c8336123e4..05a36ec87c05 100644 --- a/orchagent/switchorch.cpp +++ b/orchagent/switchorch.cpp @@ -26,6 +26,12 @@ const map switch_attribute_map = {"vxlan_router_mac", SAI_SWITCH_ATTR_VXLAN_DEFAULT_ROUTER_MAC} }; +const map switch_tunnel_attribute_map = +{ + {"vxlan_sport", SAI_SWITCH_TUNNEL_ATTR_VXLAN_UDP_SPORT}, + {"vxlan_mask", SAI_SWITCH_TUNNEL_ATTR_VXLAN_UDP_SPORT_MASK} +}; + const map packet_action_map = { {"drop", SAI_PACKET_ACTION_DROP}, @@ -127,6 +133,61 @@ void SwitchOrch::doCfgSensorsTableTask(Consumer &consumer) } } + +sai_status_t SwitchOrch::setSwitchTunnelVxlanParams(swss::FieldValueTuple &val) +{ + auto attribute = fvField(val); + auto value = fvValue(val); + sai_attribute_t attr; + sai_status_t status; + + if (!m_vxlanSportUserModeEnabled) + { + // Enable Vxlan src port range feature + vector attrs; + attr.id = SAI_SWITCH_TUNNEL_ATTR_TUNNEL_TYPE; + attr.value.s32 = SAI_TUNNEL_TYPE_VXLAN; + attrs.push_back(attr); + attr.id = SAI_SWITCH_TUNNEL_ATTR_TUNNEL_VXLAN_UDP_SPORT_MODE; + attr.value.s32 = SAI_TUNNEL_VXLAN_UDP_SPORT_MODE_USER_DEFINED; + attrs.push_back(attr); + + status = sai_switch_api->create_switch_tunnel(&m_switchTunnelId, gSwitchId, static_cast(attrs.size()), attrs.data()); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to create switch_tunnel object, rv:%d", status); + return status; + } + + m_vxlanSportUserModeEnabled = true; + } + + attr.id = switch_tunnel_attribute_map.at(attribute); + switch (attr.id) + { + case SAI_SWITCH_TUNNEL_ATTR_VXLAN_UDP_SPORT: + attr.value.u16 = to_uint(value); + break; + case SAI_SWITCH_TUNNEL_ATTR_VXLAN_UDP_SPORT_MASK: + attr.value.u8 = to_uint(value); + break; + default: + SWSS_LOG_ERROR("Invalid switch tunnel attribute id %d", attr.id); + return SAI_STATUS_SUCCESS; + } + + status = sai_switch_api->set_switch_tunnel_attribute(m_switchTunnelId, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to set tunnnel switch attribute %s to %s, rv:%d", attribute.c_str(), value.c_str(), status); + return status; + } + + SWSS_LOG_NOTICE("Set switch attribute %s to %s", attribute.c_str(), value.c_str()); + return SAI_STATUS_SUCCESS; +} + void SwitchOrch::doAppSwitchTableTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -136,19 +197,31 @@ void SwitchOrch::doAppSwitchTableTask(Consumer &consumer) { auto t = it->second; auto op = kfvOp(t); + bool retry = false; if (op == SET_COMMAND) { - bool retry = false; - for (auto i : kfvFieldsValues(t)) { auto attribute = fvField(i); if (switch_attribute_map.find(attribute) == switch_attribute_map.end()) { - SWSS_LOG_ERROR("Unsupported switch attribute %s", attribute.c_str()); - break; + // Check additionally 'switch_tunnel_attribute_map' for Switch Tunnel + if (switch_tunnel_attribute_map.find(attribute) == switch_tunnel_attribute_map.end()) + { + SWSS_LOG_ERROR("Unsupported switch attribute %s", attribute.c_str()); + break; + } + + auto status = setSwitchTunnelVxlanParams(i); + if ((status != SAI_STATUS_SUCCESS) && (handleSaiSetStatus(SAI_API_SWITCH, status) == task_need_retry)) + { + retry = true; + break; + } + + continue; } auto value = fvValue(i); diff --git a/orchagent/switchorch.h b/orchagent/switchorch.h index 3da3a07f94a1..86181e19df74 100644 --- a/orchagent/switchorch.h +++ b/orchagent/switchorch.h @@ -35,11 +35,13 @@ class SwitchOrch : public Orch void doAppSwitchTableTask(Consumer &consumer); void initSensorsTable(); void querySwitchTpidCapability(); + sai_status_t setSwitchTunnelVxlanParams(swss::FieldValueTuple &val); swss::NotificationConsumer* m_restartCheckNotificationConsumer; void doTask(swss::NotificationConsumer& consumer); swss::DBConnector *m_db; swss::Table m_switchTable; + sai_object_id_t m_switchTunnelId; // ASIC temperature sensors std::shared_ptr m_stateDb = nullptr; @@ -52,6 +54,7 @@ class SwitchOrch : public Orch bool m_numTempSensorsInitialized = false; bool m_sensorsMaxTempSupported = true; bool m_sensorsAvgTempSupported = true; + bool m_vxlanSportUserModeEnabled = false; // Information contained in the request from // external program for orchagent pre-shutdown state check diff --git a/tests/test_switch.py b/tests/test_switch.py index bad3aa00817c..93cfd1389c3f 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -40,14 +40,16 @@ def check_object(db, table, key, expected_attributes): (value, name, expected_attributes[name]) -def vxlan_switch_test(dvs, oid, port, mac): +def vxlan_switch_test(dvs, oid, port, mac, mask, sport): app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) create_entry_pst( app_db, "SWITCH_TABLE", ':', "switch", [ ("vxlan_port", port), - ("vxlan_router_mac", mac) + ("vxlan_router_mac", mac), + ("vxlan_mask", mask), + ("vxlan_sport", sport), ], ) time.sleep(2) @@ -57,6 +59,8 @@ def vxlan_switch_test(dvs, oid, port, mac): { 'SAI_SWITCH_ATTR_VXLAN_DEFAULT_PORT': port, 'SAI_SWITCH_ATTR_VXLAN_DEFAULT_ROUTER_MAC': mac, + 'SAI_SWITCH_TUNNEL_ATTR_VXLAN_UDP_SPORT_MASK': mask, + 'SAI_SWITCH_TUNNEL_ATTR_VXLAN_UDP_SPORT': sport, } ) @@ -67,10 +71,9 @@ class TestSwitch(object): ''' def test_switch_attribute(self, dvs, testlog): switch_oid = get_exist_entry(dvs, "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH") + vxlan_switch_test(dvs, switch_oid, "12345", "00:01:02:03:04:05", "20", "54321") - vxlan_switch_test(dvs, switch_oid, "12345", "00:01:02:03:04:05") - - vxlan_switch_test(dvs, switch_oid, "56789", "00:0A:0B:0C:0D:0E") + vxlan_switch_test(dvs, switch_oid, "56789", "00:0A:0B:0C:0D:0E", "15", "56789") # Add Dummy always-pass test at end as workaroud