Skip to content

Commit f7214d9

Browse files
theasianpianistshiraez
authored andcommitted
[dash] Implement PL and route group API (sonic-net#3048)
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
1 parent 8a5b757 commit f7214d9

26 files changed

+1733
-645
lines changed

.azure-pipelines/build-docker-sonic-vs-template.yml

+5-2
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,12 @@ jobs:
8888
project: ${{ parameters.sairedis_artifact_project }}
8989
pipeline: ${{ parameters.sairedis_artifact_pipeline }}
9090
artifact: ${{ parameters.sairedis_artifact_name }}
91-
runVersion: 'latestFromBranch'
92-
runBranch: 'refs/heads/${{ parameters.sairedis_artifact_branch }}'
91+
runVersion: 'specific'
92+
pipelineId: 613643
93+
# runVersion: 'latestFromBranch'
94+
# runBranch: 'refs/heads/${{ parameters.sairedis_artifact_branch }}'
9395
allowPartiallySucceededBuilds: true
96+
allowFailedBuilds: true
9497
path: $(Build.ArtifactStagingDirectory)/download/sairedis
9598
patterns: |
9699
${{ parameters.sairedis_artifact_pattern }}/libsaivs_*.deb

.azure-pipelines/build-template.yml

+5-2
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,12 @@ jobs:
127127
project: ${{ parameters.sairedis_artifact_project }}
128128
pipeline: ${{ parameters.sairedis_artifact_pipeline }}
129129
artifact: ${{ parameters.sairedis_artifact_name }}
130-
runVersion: 'latestFromBranch'
131-
runBranch: 'refs/heads/${{ parameters.sairedis_artifact_branch }}'
130+
runVersion: 'specific'
131+
pipelineId: 613643
132+
# runVersion: 'latestFromBranch'
133+
# runBranch: 'refs/heads/${{ parameters.sairedis_artifact_branch }}'
132134
allowPartiallySucceededBuilds: true
135+
allowFailedBuilds: true
133136
path: $(Build.ArtifactStagingDirectory)/download/sairedis
134137
patterns: |
135138
${{ parameters.sairedis_artifact_pattern }}/libsaivs_*.deb

.azure-pipelines/test-docker-sonic-vs-template.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ jobs:
136136
fi
137137
138138
all_tests=$(ls test_*.py | xargs)
139-
all_tests="${all_tests} p4rt"
139+
all_tests="${all_tests} p4rt dash"
140140
141141
if [ -n '${{ parameters.run_tests_pattern }}' ]; then
142142
all_tests=" $(ls ${{ parameters.run_tests_pattern }} | xargs) "

orchagent/bulker.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ static inline bool operator==(const sai_pa_validation_entry_t& a, const sai_pa_v
134134
static inline bool operator==(const sai_outbound_routing_entry_t& a, const sai_outbound_routing_entry_t& b)
135135
{
136136
return a.switch_id == b.switch_id
137-
&& a.eni_id == b.eni_id
137+
&& a.outbound_routing_group_id == b.outbound_routing_group_id
138138
&& a.destination == b.destination
139139
;
140140
}
@@ -257,7 +257,7 @@ namespace std
257257
{
258258
size_t seed = 0;
259259
boost::hash_combine(seed, a.switch_id);
260-
boost::hash_combine(seed, a.eni_id);
260+
boost::hash_combine(seed, a.outbound_routing_group_id);
261261
boost::hash_combine(seed, a.destination);
262262
return seed;
263263
}

orchagent/dash/dashorch.cpp

+206-8
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
#include "tokenize.h"
1818
#include "crmorch.h"
1919
#include "saihelper.h"
20+
#include "directory.h"
2021

2122
#include "taskworker.h"
2223
#include "pbutils.h"
24+
#include "dashrouteorch.h"
2325

2426
using namespace std;
2527
using namespace swss;
2628

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

43+
bool DashOrch::getRouteTypeActions(dash::route_type::RoutingType routing_type, dash::route_type::RouteType& route_type)
44+
{
45+
SWSS_LOG_ENTER();
46+
47+
auto it = routing_type_entries_.find(routing_type);
48+
if (it == routing_type_entries_.end())
49+
{
50+
SWSS_LOG_WARN("Routing type %s not found", dash::route_type::RoutingType_Name(routing_type).c_str());
51+
return false;
52+
}
53+
54+
route_type = it->second;
55+
return true;
56+
}
57+
4058
bool DashOrch::addApplianceEntry(const string& appliance_id, const dash::appliance::Appliance &entry)
4159
{
4260
SWSS_LOG_ENTER();
@@ -191,34 +209,34 @@ void DashOrch::doTaskApplianceTable(ConsumerBase& consumer)
191209
}
192210
}
193211

194-
bool DashOrch::addRoutingTypeEntry(const string& routing_type, const dash::route_type::RouteType &entry)
212+
bool DashOrch::addRoutingTypeEntry(const dash::route_type::RoutingType& routing_type, const dash::route_type::RouteType &entry)
195213
{
196214
SWSS_LOG_ENTER();
197215

198216
if (routing_type_entries_.find(routing_type) != routing_type_entries_.end())
199217
{
200-
SWSS_LOG_WARN("Routing type entry already exists for %s", routing_type.c_str());
218+
SWSS_LOG_WARN("Routing type entry already exists for %s", dash::route_type::RoutingType_Name(routing_type).c_str());
201219
return true;
202220
}
203221

204222
routing_type_entries_[routing_type] = entry;
205-
SWSS_LOG_NOTICE("Routing type entry added %s", routing_type.c_str());
223+
SWSS_LOG_NOTICE("Routing type entry added %s", dash::route_type::RoutingType_Name(routing_type).c_str());
206224

207225
return true;
208226
}
209227

210-
bool DashOrch::removeRoutingTypeEntry(const string& routing_type)
228+
bool DashOrch::removeRoutingTypeEntry(const dash::route_type::RoutingType& routing_type)
211229
{
212230
SWSS_LOG_ENTER();
213231

214232
if (routing_type_entries_.find(routing_type) == routing_type_entries_.end())
215233
{
216-
SWSS_LOG_WARN("Routing type entry does not exist for %s", routing_type.c_str());
234+
SWSS_LOG_WARN("Routing type entry does not exist for %s", dash::route_type::RoutingType_Name(routing_type).c_str());
217235
return true;
218236
}
219237

220238
routing_type_entries_.erase(routing_type);
221-
SWSS_LOG_NOTICE("Routing type entry removed for %s", routing_type.c_str());
239+
SWSS_LOG_NOTICE("Routing type entry removed for %s", dash::route_type::RoutingType_Name(routing_type).c_str());
222240

223241
return true;
224242
}
@@ -231,16 +249,27 @@ void DashOrch::doTaskRoutingTypeTable(ConsumerBase& consumer)
231249
while (it != consumer.m_toSync.end())
232250
{
233251
KeyOpFieldsValuesTuple t = it->second;
234-
string routing_type = kfvKey(t);
252+
string routing_type_str = kfvKey(t);
235253
string op = kfvOp(t);
254+
dash::route_type::RoutingType routing_type;
255+
256+
std::transform(routing_type_str.begin(), routing_type_str.end(), routing_type_str.begin(), ::toupper);
257+
routing_type_str = "ROUTING_TYPE_" + routing_type_str;
258+
259+
if (!dash::route_type::RoutingType_Parse(routing_type_str, &routing_type))
260+
{
261+
SWSS_LOG_WARN("Invalid routing type %s", routing_type_str.c_str());
262+
it = consumer.m_toSync.erase(it);
263+
continue;
264+
}
236265

237266
if (op == SET_COMMAND)
238267
{
239268
dash::route_type::RouteType entry;
240269

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

390+
if (entry.metadata.has_pl_underlay_sip())
391+
{
392+
eni_attr.id = SAI_ENI_ATTR_PL_UNDERLAY_SIP;
393+
to_sai(entry.metadata.pl_underlay_sip(), eni_attr.value.ipaddr);
394+
eni_attrs.push_back(eni_attr);
395+
}
396+
397+
// auto eni_route_it = eni_route_entries_.find(eni);
398+
// if (eni_route_it != eni_route_entries_.end())
399+
// {
400+
// SWSS_LOG_INFO("ENI %s has route group %s", eni.c_str(), eni_route_it->second.group_id().c_str());
401+
// DashRouteOrch *dash_route_orch = gDirectory.get<DashRouteOrch*>();
402+
// eni_attr.id = SAI_ENI_ATTR_OUTBOUND_ROUTING_GROUP_ID;
403+
// eni_attr.value.oid = dash_route_orch->getRouteGroupOid(eni_route_it->second.group_id());
404+
// eni_attrs.push_back(eni_attr);
405+
// }
406+
361407
sai_status_t status = sai_dash_eni_api->create_eni(&eni_id, gSwitchId,
362408
(uint32_t)eni_attrs.size(), eni_attrs.data());
363409
if (status != SAI_STATUS_SUCCESS)
@@ -653,6 +699,154 @@ void DashOrch::doTaskQosTable(ConsumerBase& consumer)
653699
}
654700
}
655701

702+
bool DashOrch::setEniRoute(const std::string& eni, const dash::eni_route::EniRoute& entry)
703+
{
704+
SWSS_LOG_ENTER();
705+
706+
707+
if (eni_entries_.find(eni) == eni_entries_.end())
708+
{
709+
SWSS_LOG_INFO("ENI %s not yet created, not programming ENI route entry", eni.c_str());
710+
return false;
711+
}
712+
713+
DashRouteOrch *dash_route_orch = gDirectory.get<DashRouteOrch*>();
714+
sai_object_id_t route_group_oid = dash_route_orch->getRouteGroupOid(entry.group_id());
715+
if (route_group_oid == SAI_NULL_OBJECT_ID)
716+
{
717+
SWSS_LOG_INFO("Route group not yet created, skipping route entry for ENI %s", entry.group_id().c_str());
718+
return false;
719+
}
720+
721+
std::string old_group_id;
722+
if (eni_route_entries_.find(eni) != eni_route_entries_.end())
723+
{
724+
if (eni_route_entries_[eni].group_id() != entry.group_id())
725+
{
726+
old_group_id = eni_route_entries_[eni].group_id();
727+
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());
728+
}
729+
else
730+
{
731+
SWSS_LOG_WARN("Duplicate ENI route entry already exists for %s", eni.c_str());
732+
return true;
733+
}
734+
}
735+
736+
sai_attribute_t eni_attr;
737+
eni_attr.id = SAI_ENI_ATTR_OUTBOUND_ROUTING_GROUP_ID;
738+
eni_attr.value.oid = route_group_oid;
739+
740+
sai_status_t status = sai_dash_eni_api->set_eni_attribute(eni_entries_[eni].eni_id,
741+
&eni_attr);
742+
743+
if (status != SAI_STATUS_SUCCESS)
744+
{
745+
SWSS_LOG_ERROR("Failed to set ENI route group for %s", eni.c_str());
746+
task_process_status handle_status = handleSaiSetStatus((sai_api_t) SAI_API_DASH_ENI, status);
747+
if (handle_status != task_success)
748+
{
749+
return parseHandleSaiStatusFailure(handle_status);
750+
}
751+
}
752+
eni_route_entries_[eni] = entry;
753+
dash_route_orch->bindRouteGroup(entry.group_id());
754+
755+
if (!old_group_id.empty())
756+
{
757+
dash_route_orch->unbindRouteGroup(old_group_id);
758+
}
759+
760+
SWSS_LOG_NOTICE("Updated ENI route group for %s to route group %s", eni.c_str(), entry.group_id().c_str());
761+
return true;
762+
}
763+
764+
bool DashOrch::removeEniRoute(const std::string& eni)
765+
{
766+
SWSS_LOG_ENTER();
767+
768+
if (eni_route_entries_.find(eni) == eni_route_entries_.end())
769+
{
770+
SWSS_LOG_WARN("ENI route entry does not exist for %s", eni.c_str());
771+
return true;
772+
}
773+
774+
if (eni_entries_.find(eni) != eni_entries_.end())
775+
{
776+
sai_attribute_t eni_attr;
777+
eni_attr.id = SAI_ENI_ATTR_OUTBOUND_ROUTING_GROUP_ID;
778+
eni_attr.value.oid = SAI_NULL_OBJECT_ID;
779+
780+
sai_status_t status = sai_dash_eni_api->set_eni_attribute(eni_entries_[eni].eni_id,
781+
&eni_attr);
782+
if (status != SAI_STATUS_SUCCESS)
783+
{
784+
SWSS_LOG_ERROR("Failed to remove ENI route for %s", eni.c_str());
785+
task_process_status handle_status = handleSaiSetStatus((sai_api_t) SAI_API_DASH_ENI, status);
786+
if (handle_status != task_success)
787+
{
788+
return parseHandleSaiStatusFailure(handle_status);
789+
}
790+
}
791+
}
792+
793+
DashRouteOrch *dash_route_orch = gDirectory.get<DashRouteOrch*>();
794+
dash_route_orch->unbindRouteGroup(eni_route_entries_[eni].group_id());
795+
eni_route_entries_.erase(eni);
796+
797+
SWSS_LOG_NOTICE("Removed ENI route entry for %s", eni.c_str());
798+
799+
return true;
800+
}
801+
802+
void DashOrch::doTaskEniRouteTable(ConsumerBase& consumer)
803+
{
804+
auto it = consumer.m_toSync.begin();
805+
while (it != consumer.m_toSync.end())
806+
{
807+
KeyOpFieldsValuesTuple t = it->second;
808+
string eni = kfvKey(t);
809+
string op = kfvOp(t);
810+
811+
if (op == SET_COMMAND)
812+
{
813+
dash::eni_route::EniRoute entry;
814+
815+
if (!parsePbMessage(kfvFieldsValues(t), entry))
816+
{
817+
SWSS_LOG_WARN("Requires protobuf at ENI route:%s", eni.c_str());
818+
it = consumer.m_toSync.erase(it);
819+
continue;
820+
}
821+
822+
if (setEniRoute(eni, entry))
823+
{
824+
it = consumer.m_toSync.erase(it);
825+
}
826+
else
827+
{
828+
it++;
829+
}
830+
}
831+
else if (op == DEL_COMMAND)
832+
{
833+
if (removeEniRoute(eni))
834+
{
835+
it = consumer.m_toSync.erase(it);
836+
}
837+
else
838+
{
839+
it++;
840+
}
841+
}
842+
else
843+
{
844+
SWSS_LOG_ERROR("Unknown operation %s", op.c_str());
845+
it = consumer.m_toSync.erase(it);
846+
}
847+
}
848+
}
849+
656850
void DashOrch::doTask(ConsumerBase& consumer)
657851
{
658852
SWSS_LOG_ENTER();
@@ -677,6 +871,10 @@ void DashOrch::doTask(ConsumerBase& consumer)
677871
{
678872
doTaskQosTable(consumer);
679873
}
874+
else if (tn == APP_DASH_ENI_ROUTE_TABLE_NAME)
875+
{
876+
doTaskEniRouteTable(consumer);
877+
}
680878
else
681879
{
682880
SWSS_LOG_ERROR("Unknown table: %s", tn.c_str());

0 commit comments

Comments
 (0)