Skip to content

Commit

Permalink
[dash] Implement PL and route group API (#3048)
Browse files Browse the repository at this point in the history
Implement SAI attributes needed for private link
Update dashorchs to use new route group API
Update existing DASH tests to use new route group API
Add new PL tests
  • Loading branch information
theasianpianist authored Sep 6, 2024
1 parent 42ea859 commit 5fd7a05
Show file tree
Hide file tree
Showing 26 changed files with 1,733 additions and 645 deletions.
7 changes: 5 additions & 2 deletions .azure-pipelines/build-docker-sonic-vs-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,12 @@ jobs:
project: ${{ parameters.sairedis_artifact_project }}
pipeline: ${{ parameters.sairedis_artifact_pipeline }}
artifact: ${{ parameters.sairedis_artifact_name }}
runVersion: 'latestFromBranch'
runBranch: 'refs/heads/${{ parameters.sairedis_artifact_branch }}'
runVersion: 'specific'
pipelineId: 613643
# runVersion: 'latestFromBranch'
# runBranch: 'refs/heads/${{ parameters.sairedis_artifact_branch }}'
allowPartiallySucceededBuilds: true
allowFailedBuilds: true
path: $(Build.ArtifactStagingDirectory)/download/sairedis
patterns: |
${{ parameters.sairedis_artifact_pattern }}/libsaivs_*.deb
Expand Down
7 changes: 5 additions & 2 deletions .azure-pipelines/build-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,12 @@ jobs:
project: ${{ parameters.sairedis_artifact_project }}
pipeline: ${{ parameters.sairedis_artifact_pipeline }}
artifact: ${{ parameters.sairedis_artifact_name }}
runVersion: 'latestFromBranch'
runBranch: 'refs/heads/${{ parameters.sairedis_artifact_branch }}'
runVersion: 'specific'
pipelineId: 613643
# runVersion: 'latestFromBranch'
# runBranch: 'refs/heads/${{ parameters.sairedis_artifact_branch }}'
allowPartiallySucceededBuilds: true
allowFailedBuilds: true
path: $(Build.ArtifactStagingDirectory)/download/sairedis
patterns: |
${{ parameters.sairedis_artifact_pattern }}/libsaivs_*.deb
Expand Down
2 changes: 1 addition & 1 deletion .azure-pipelines/test-docker-sonic-vs-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ jobs:
fi
all_tests=$(ls test_*.py | xargs)
all_tests="${all_tests} p4rt"
all_tests="${all_tests} p4rt dash"
if [ -n '${{ parameters.run_tests_pattern }}' ]; then
all_tests=" $(ls ${{ parameters.run_tests_pattern }} | xargs) "
Expand Down
4 changes: 2 additions & 2 deletions orchagent/bulker.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static inline bool operator==(const sai_pa_validation_entry_t& a, const sai_pa_v
static inline bool operator==(const sai_outbound_routing_entry_t& a, const sai_outbound_routing_entry_t& b)
{
return a.switch_id == b.switch_id
&& a.eni_id == b.eni_id
&& a.outbound_routing_group_id == b.outbound_routing_group_id
&& a.destination == b.destination
;
}
Expand Down Expand Up @@ -257,7 +257,7 @@ namespace std
{
size_t seed = 0;
boost::hash_combine(seed, a.switch_id);
boost::hash_combine(seed, a.eni_id);
boost::hash_combine(seed, a.outbound_routing_group_id);
boost::hash_combine(seed, a.destination);
return seed;
}
Expand Down
214 changes: 206 additions & 8 deletions orchagent/dash/dashorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
#include "tokenize.h"
#include "crmorch.h"
#include "saihelper.h"
#include "directory.h"

#include "taskworker.h"
#include "pbutils.h"
#include "dashrouteorch.h"

using namespace std;
using namespace swss;

extern Directory<Orch*> gDirectory;
extern std::unordered_map<std::string, sai_object_id_t> gVnetNameToId;
extern sai_dash_vip_api_t* sai_dash_vip_api;
extern sai_dash_direction_lookup_api_t* sai_dash_direction_lookup_api;
Expand All @@ -37,6 +40,21 @@ DashOrch::DashOrch(DBConnector *db, vector<string> &tableName, ZmqServer *zmqSer
SWSS_LOG_ENTER();
}

bool DashOrch::getRouteTypeActions(dash::route_type::RoutingType routing_type, dash::route_type::RouteType& route_type)
{
SWSS_LOG_ENTER();

auto it = routing_type_entries_.find(routing_type);
if (it == routing_type_entries_.end())
{
SWSS_LOG_WARN("Routing type %s not found", dash::route_type::RoutingType_Name(routing_type).c_str());
return false;
}

route_type = it->second;
return true;
}

bool DashOrch::addApplianceEntry(const string& appliance_id, const dash::appliance::Appliance &entry)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -191,34 +209,34 @@ void DashOrch::doTaskApplianceTable(ConsumerBase& consumer)
}
}

bool DashOrch::addRoutingTypeEntry(const string& routing_type, const dash::route_type::RouteType &entry)
bool DashOrch::addRoutingTypeEntry(const dash::route_type::RoutingType& routing_type, const dash::route_type::RouteType &entry)
{
SWSS_LOG_ENTER();

if (routing_type_entries_.find(routing_type) != routing_type_entries_.end())
{
SWSS_LOG_WARN("Routing type entry already exists for %s", routing_type.c_str());
SWSS_LOG_WARN("Routing type entry already exists for %s", dash::route_type::RoutingType_Name(routing_type).c_str());
return true;
}

routing_type_entries_[routing_type] = entry;
SWSS_LOG_NOTICE("Routing type entry added %s", routing_type.c_str());
SWSS_LOG_NOTICE("Routing type entry added %s", dash::route_type::RoutingType_Name(routing_type).c_str());

return true;
}

bool DashOrch::removeRoutingTypeEntry(const string& routing_type)
bool DashOrch::removeRoutingTypeEntry(const dash::route_type::RoutingType& routing_type)
{
SWSS_LOG_ENTER();

if (routing_type_entries_.find(routing_type) == routing_type_entries_.end())
{
SWSS_LOG_WARN("Routing type entry does not exist for %s", routing_type.c_str());
SWSS_LOG_WARN("Routing type entry does not exist for %s", dash::route_type::RoutingType_Name(routing_type).c_str());
return true;
}

routing_type_entries_.erase(routing_type);
SWSS_LOG_NOTICE("Routing type entry removed for %s", routing_type.c_str());
SWSS_LOG_NOTICE("Routing type entry removed for %s", dash::route_type::RoutingType_Name(routing_type).c_str());

return true;
}
Expand All @@ -231,16 +249,27 @@ void DashOrch::doTaskRoutingTypeTable(ConsumerBase& consumer)
while (it != consumer.m_toSync.end())
{
KeyOpFieldsValuesTuple t = it->second;
string routing_type = kfvKey(t);
string routing_type_str = kfvKey(t);
string op = kfvOp(t);
dash::route_type::RoutingType routing_type;

std::transform(routing_type_str.begin(), routing_type_str.end(), routing_type_str.begin(), ::toupper);
routing_type_str = "ROUTING_TYPE_" + routing_type_str;

if (!dash::route_type::RoutingType_Parse(routing_type_str, &routing_type))
{
SWSS_LOG_WARN("Invalid routing type %s", routing_type_str.c_str());
it = consumer.m_toSync.erase(it);
continue;
}

if (op == SET_COMMAND)
{
dash::route_type::RouteType entry;

if (!parsePbMessage(kfvFieldsValues(t), entry))
{
SWSS_LOG_WARN("Requires protobuff at routing type :%s", routing_type.c_str());
SWSS_LOG_WARN("Requires protobuff at routing type :%s", routing_type_str.c_str());
it = consumer.m_toSync.erase(it);
continue;
}
Expand Down Expand Up @@ -358,6 +387,23 @@ bool DashOrch::addEniObject(const string& eni, EniEntry& entry)
eni_attr.value.u32 = app_entry.vm_vni();
eni_attrs.push_back(eni_attr);

if (entry.metadata.has_pl_underlay_sip())
{
eni_attr.id = SAI_ENI_ATTR_PL_UNDERLAY_SIP;
to_sai(entry.metadata.pl_underlay_sip(), eni_attr.value.ipaddr);
eni_attrs.push_back(eni_attr);
}

// auto eni_route_it = eni_route_entries_.find(eni);
// if (eni_route_it != eni_route_entries_.end())
// {
// SWSS_LOG_INFO("ENI %s has route group %s", eni.c_str(), eni_route_it->second.group_id().c_str());
// DashRouteOrch *dash_route_orch = gDirectory.get<DashRouteOrch*>();
// eni_attr.id = SAI_ENI_ATTR_OUTBOUND_ROUTING_GROUP_ID;
// eni_attr.value.oid = dash_route_orch->getRouteGroupOid(eni_route_it->second.group_id());
// eni_attrs.push_back(eni_attr);
// }

sai_status_t status = sai_dash_eni_api->create_eni(&eni_id, gSwitchId,
(uint32_t)eni_attrs.size(), eni_attrs.data());
if (status != SAI_STATUS_SUCCESS)
Expand Down Expand Up @@ -653,6 +699,154 @@ void DashOrch::doTaskQosTable(ConsumerBase& consumer)
}
}

bool DashOrch::setEniRoute(const std::string& eni, const dash::eni_route::EniRoute& entry)
{
SWSS_LOG_ENTER();


if (eni_entries_.find(eni) == eni_entries_.end())
{
SWSS_LOG_INFO("ENI %s not yet created, not programming ENI route entry", eni.c_str());
return false;
}

DashRouteOrch *dash_route_orch = gDirectory.get<DashRouteOrch*>();
sai_object_id_t route_group_oid = dash_route_orch->getRouteGroupOid(entry.group_id());
if (route_group_oid == SAI_NULL_OBJECT_ID)
{
SWSS_LOG_INFO("Route group not yet created, skipping route entry for ENI %s", entry.group_id().c_str());
return false;
}

std::string old_group_id;
if (eni_route_entries_.find(eni) != eni_route_entries_.end())
{
if (eni_route_entries_[eni].group_id() != entry.group_id())
{
old_group_id = eni_route_entries_[eni].group_id();
SWSS_LOG_INFO("Updating route entry from %s to %s for ENI %s", eni_route_entries_[eni].group_id().c_str(), entry.group_id().c_str(), eni.c_str());
}
else
{
SWSS_LOG_WARN("Duplicate ENI route entry already exists for %s", eni.c_str());
return true;
}
}

sai_attribute_t eni_attr;
eni_attr.id = SAI_ENI_ATTR_OUTBOUND_ROUTING_GROUP_ID;
eni_attr.value.oid = route_group_oid;

sai_status_t status = sai_dash_eni_api->set_eni_attribute(eni_entries_[eni].eni_id,
&eni_attr);

if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to set ENI route group for %s", eni.c_str());
task_process_status handle_status = handleSaiSetStatus((sai_api_t) SAI_API_DASH_ENI, status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
}
eni_route_entries_[eni] = entry;
dash_route_orch->bindRouteGroup(entry.group_id());

if (!old_group_id.empty())
{
dash_route_orch->unbindRouteGroup(old_group_id);
}

SWSS_LOG_NOTICE("Updated ENI route group for %s to route group %s", eni.c_str(), entry.group_id().c_str());
return true;
}

bool DashOrch::removeEniRoute(const std::string& eni)
{
SWSS_LOG_ENTER();

if (eni_route_entries_.find(eni) == eni_route_entries_.end())
{
SWSS_LOG_WARN("ENI route entry does not exist for %s", eni.c_str());
return true;
}

if (eni_entries_.find(eni) != eni_entries_.end())
{
sai_attribute_t eni_attr;
eni_attr.id = SAI_ENI_ATTR_OUTBOUND_ROUTING_GROUP_ID;
eni_attr.value.oid = SAI_NULL_OBJECT_ID;

sai_status_t status = sai_dash_eni_api->set_eni_attribute(eni_entries_[eni].eni_id,
&eni_attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to remove ENI route for %s", eni.c_str());
task_process_status handle_status = handleSaiSetStatus((sai_api_t) SAI_API_DASH_ENI, status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
}
}

DashRouteOrch *dash_route_orch = gDirectory.get<DashRouteOrch*>();
dash_route_orch->unbindRouteGroup(eni_route_entries_[eni].group_id());
eni_route_entries_.erase(eni);

SWSS_LOG_NOTICE("Removed ENI route entry for %s", eni.c_str());

return true;
}

void DashOrch::doTaskEniRouteTable(ConsumerBase& consumer)
{
auto it = consumer.m_toSync.begin();
while (it != consumer.m_toSync.end())
{
KeyOpFieldsValuesTuple t = it->second;
string eni = kfvKey(t);
string op = kfvOp(t);

if (op == SET_COMMAND)
{
dash::eni_route::EniRoute entry;

if (!parsePbMessage(kfvFieldsValues(t), entry))
{
SWSS_LOG_WARN("Requires protobuf at ENI route:%s", eni.c_str());
it = consumer.m_toSync.erase(it);
continue;
}

if (setEniRoute(eni, entry))
{
it = consumer.m_toSync.erase(it);
}
else
{
it++;
}
}
else if (op == DEL_COMMAND)
{
if (removeEniRoute(eni))
{
it = consumer.m_toSync.erase(it);
}
else
{
it++;
}
}
else
{
SWSS_LOG_ERROR("Unknown operation %s", op.c_str());
it = consumer.m_toSync.erase(it);
}
}
}

void DashOrch::doTask(ConsumerBase& consumer)
{
SWSS_LOG_ENTER();
Expand All @@ -677,6 +871,10 @@ void DashOrch::doTask(ConsumerBase& consumer)
{
doTaskQosTable(consumer);
}
else if (tn == APP_DASH_ENI_ROUTE_TABLE_NAME)
{
doTaskEniRouteTable(consumer);
}
else
{
SWSS_LOG_ERROR("Unknown table: %s", tn.c_str());
Expand Down
Loading

0 comments on commit 5fd7a05

Please sign in to comment.