Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions orchagent/nexthopgroupkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class NextHopGroupKey
{
m_overlay_nexthops = false;
m_srv6_nexthops = false;
m_srv6_vpn = false;
auto nhv = tokenize(nexthops, NHG_DELIMITER);
for (const auto &nh : nhv)
{
Expand All @@ -27,6 +28,7 @@ class NextHopGroupKey
{
m_overlay_nexthops = true;
m_srv6_nexthops = false;
m_srv6_vpn = false;
auto nhv = tokenize(nexthops, NHG_DELIMITER);
for (const auto &nh_str : nhv)
{
Expand All @@ -38,11 +40,16 @@ class NextHopGroupKey
{
m_overlay_nexthops = false;
m_srv6_nexthops = true;
m_srv6_vpn = false;
auto nhv = tokenize(nexthops, NHG_DELIMITER);
for (const auto &nh_str : nhv)
{
auto nh = NextHopKey(nh_str, overlay_nh, srv6_nh);
m_nexthops.insert(nh);
if (nh.isSrv6Vpn())
{
m_srv6_vpn = true;
}
}
}
}
Expand All @@ -51,6 +58,7 @@ class NextHopGroupKey
{
m_overlay_nexthops = false;
m_srv6_nexthops = false;
m_srv6_vpn = false;
std::vector<std::string> nhv = tokenize(nexthops, NHG_DELIMITER);
std::vector<std::string> wtv = tokenize(weights, NHG_DELIMITER);
bool set_weight = wtv.size() == nhv.size();
Expand Down Expand Up @@ -221,15 +229,21 @@ class NextHopGroupKey
return m_srv6_nexthops;
}

inline bool is_srv6_vpn() const
{
return m_srv6_vpn;
}

void clear()
{
m_nexthops.clear();
}

private:
std::set<NextHopKey> m_nexthops;
bool m_overlay_nexthops;
bool m_srv6_nexthops;
bool m_overlay_nexthops = false;
bool m_srv6_nexthops = false;
bool m_srv6_vpn = false;
};

#endif /* SWSS_NEXTHOPGROUPKEY_H */
21 changes: 15 additions & 6 deletions orchagent/nexthopkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct NextHopKey
uint32_t weight; // NH weight for NHGs
string srv6_segment; // SRV6 segment string
string srv6_source; // SRV6 source address
string srv6_vpn_sid; // SRV6 vpn sid

NextHopKey() : weight(0) {}
NextHopKey(const std::string &str, const std::string &alias) :
Expand Down Expand Up @@ -76,14 +77,15 @@ struct NextHopKey
vni = 0;
weight = 0;
auto keys = tokenize(str, NH_DELIMITER);
if (keys.size() != 3)
if (keys.size() != 4)
{
std::string err = "Error converting " + str + " to Nexthop";
throw std::invalid_argument(err);
}
ip_address = keys[0];
srv6_segment = keys[1];
srv6_source = keys[2];
srv6_vpn_sid = keys[3];
}
else
{
Expand Down Expand Up @@ -115,7 +117,8 @@ struct NextHopKey
{
if (srv6_nh)
{
return ip_address.to_string() + NH_DELIMITER + srv6_segment + NH_DELIMITER + srv6_source;
return ip_address.to_string() + NH_DELIMITER + srv6_segment + NH_DELIMITER + srv6_source + NH_DELIMITER
+ srv6_vpn_sid + NH_DELIMITER;
}
std::string str = formatMplsNextHop();
str += (ip_address.to_string() + NH_DELIMITER + alias + NH_DELIMITER +
Expand All @@ -125,16 +128,17 @@ struct NextHopKey

bool operator<(const NextHopKey &o) const
{
return tie(ip_address, alias, label_stack, vni, mac_address, srv6_segment, srv6_source) <
tie(o.ip_address, o.alias, o.label_stack, o.vni, o.mac_address, o.srv6_segment, o.srv6_source);
return tie(ip_address, alias, label_stack, vni, mac_address, srv6_segment, srv6_source, srv6_vpn_sid) <
tie(o.ip_address, o.alias, o.label_stack, o.vni, o.mac_address, o.srv6_segment, o.srv6_source, o.srv6_vpn_sid);
}

bool operator==(const NextHopKey &o) const
{
return (ip_address == o.ip_address) && (alias == o.alias) &&
(label_stack == o.label_stack) &&
(vni == o.vni) && (mac_address == o.mac_address) &&
(srv6_segment == o.srv6_segment) && (srv6_source == o.srv6_source);
(srv6_segment == o.srv6_segment) && (srv6_source == o.srv6_source) &&
(srv6_vpn_sid == o.srv6_vpn_sid);
}

bool operator!=(const NextHopKey &o) const
Expand All @@ -154,7 +158,12 @@ struct NextHopKey

bool isSrv6NextHop() const
{
return (srv6_segment != "");
return ((srv6_segment != "") || (srv6_vpn_sid != "") || (srv6_source != ""));
}

bool isSrv6Vpn() const
{
return (srv6_vpn_sid != "");
}

std::string parseMplsNextHop(const std::string& str)
Expand Down
125 changes: 112 additions & 13 deletions orchagent/nhgorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "neighorch.h"
#include "crmorch.h"
#include "routeorch.h"
#include "srv6orch.h"
#include "bulker.h"
#include "logger.h"
#include "swssnet.h"
Expand All @@ -12,6 +13,7 @@ extern IntfsOrch *gIntfsOrch;
extern NeighOrch *gNeighOrch;
extern RouteOrch *gRouteOrch;
extern NhgOrch *gNhgOrch;
extern Srv6Orch *gSrv6Orch;

extern size_t gMaxBulkSize;

Expand Down Expand Up @@ -61,6 +63,9 @@ void NhgOrch::doTask(Consumer& consumer)
string mpls_nhs;
string nhgs;
bool is_recursive = false;
string srv6_source;
bool overlay_nh = false;
bool srv6_nh = false;

/* Get group's next hop IPs and aliases */
for (auto i : kfvFieldsValues(t))
Expand All @@ -77,6 +82,12 @@ void NhgOrch::doTask(Consumer& consumer)
if (fvField(i) == "mpls_nh")
mpls_nhs = fvValue(i);

if (fvField(i) == "seg_src")
{
srv6_source = fvValue(i);
srv6_nh = true;
}

if (fvField(i) == "nexthop_group")
{
nhgs = fvValue(i);
Expand All @@ -96,9 +107,11 @@ void NhgOrch::doTask(Consumer& consumer)
vector<string> alsv = tokenize(aliases, ',');
vector<string> mpls_nhv = tokenize(mpls_nhs, ',');
vector<string> nhgv = tokenize(nhgs, NHG_DELIMITER);
vector<string> srv6_srcv = tokenize(srv6_source, ',');

/* Create the next hop group key. */
string nhg_str;
NextHopGroupKey nhg_key;

/* Keeps track of any non-existing member of a recursive nexthop group */
bool non_existent_member = false;
Expand Down Expand Up @@ -154,28 +167,77 @@ void NhgOrch::doTask(Consumer& consumer)
/* Form nexthopgroup key with the nexthopgroup keys of available members */
nhgv = tokenize(nhgs, NHG_DELIMITER);

bool nhg_mismatch = false;
for (uint32_t i = 0; i < nhgv.size(); i++)
{
if (i) nhg_str += NHG_DELIMITER;
auto k = m_syncdNextHopGroups.at(nhgv[i]).nhg->getKey();
if (i)
{
if (k.is_srv6_nexthop() != srv6_nh || k.is_overlay_nexthop() != overlay_nh)
{
SWSS_LOG_ERROR("Inconsistent nexthop group type between %s and %s",
m_syncdNextHopGroups.at(nhgv[0]).nhg->getKey().to_string().c_str(),
k.to_string().c_str());
nhg_mismatch = true;
break;
}
nhg_str += NHG_DELIMITER;
}
else
{
srv6_nh = k.is_srv6_nexthop();
overlay_nh = k.is_overlay_nexthop();
}

nhg_str += m_syncdNextHopGroups.at(nhgv[i]).nhg->getKey().to_string();
}

if (nhg_mismatch)
{
it = consumer.m_toSync.erase(it);
continue;
}

if (srv6_nh)
nhg_key = NextHopGroupKey(nhg_str, overlay_nh, srv6_nh);
else
nhg_key = NextHopGroupKey(nhg_str, weights);
}
else
{
for (uint32_t i = 0; i < ipv.size(); i++)
if (srv6_nh)
{
if (i) nhg_str += NHG_DELIMITER;
if (!mpls_nhv.empty() && mpls_nhv[i] != "na")
if (ipv.size() != srv6_srcv.size())
{
SWSS_LOG_ERROR("inconsistent number of endpoints and srv6_srcs.");
it = consumer.m_toSync.erase(it);
continue;
}
for (uint32_t i = 0; i < ipv.size(); i++)
{
nhg_str += mpls_nhv[i] + LABELSTACK_DELIMITER;
if (i) nhg_str += NHG_DELIMITER;
nhg_str += ipv[i] + NH_DELIMITER; // ip address
nhg_str += NH_DELIMITER; // srv6 segment
nhg_str += srv6_srcv[i] + NH_DELIMITER; // srv6 source
nhg_str += NH_DELIMITER; // srv6 vpn sid
}
nhg_key = NextHopGroupKey(nhg_str, overlay_nh, srv6_nh);
}
else
{
for (uint32_t i = 0; i < ipv.size(); i++)
{
if (i) nhg_str += NHG_DELIMITER;
if (!mpls_nhv.empty() && mpls_nhv[i] != "na")
{
nhg_str += mpls_nhv[i] + LABELSTACK_DELIMITER;
}
nhg_str += ipv[i] + NH_DELIMITER + alsv[i];
}
nhg_str += ipv[i] + NH_DELIMITER + alsv[i];
nhg_key = NextHopGroupKey(nhg_str, weights);
}
}

NextHopGroupKey nhg_key = NextHopGroupKey(nhg_str, weights);

/* If the group does not exist, create one. */
if (nhg_it == m_syncdNextHopGroups.end())
{
Expand All @@ -192,6 +254,13 @@ void NhgOrch::doTask(Consumer& consumer)
{
SWSS_LOG_DEBUG("Next hop group count reached its limit.");

// don't create temp nhg for srv6
if (nhg_key.is_srv6_nexthop())
{
++it;
continue;
}

try
{
auto nhg = std::make_unique<NextHopGroup>(createTempNhg(nhg_key));
Expand Down Expand Up @@ -476,6 +545,14 @@ sai_object_id_t NextHopGroupMember::getNhId() const
else if (gNeighOrch->hasNextHop(m_key))
{
nh_id = gNeighOrch->getNextHopId(m_key);
if (m_key.isSrv6NextHop())
{
SWSS_LOG_INFO("Single NH: create srv6 nexthop %s", m_key.to_string(false, true).c_str());
if (!gSrv6Orch->createSrv6NexthopWithoutVpn(m_key, nh_id))
{
SWSS_LOG_ERROR("Failed to create SRv6 nexthop %s", m_key.to_string(false, true).c_str());
}
}
}
/*
* If the next hop is labeled and the IP next hop exists, create the
Expand All @@ -494,7 +571,20 @@ sai_object_id_t NextHopGroupMember::getNhId() const
}
else
{
gNeighOrch->resolveNeighbor(m_key);
if (m_key.isSrv6NextHop())
{
SWSS_LOG_INFO("Single NH: create srv6 nexthop %s", m_key.to_string(false, true).c_str());
if (!gSrv6Orch->createSrv6NexthopWithoutVpn(m_key, nh_id))
{
SWSS_LOG_ERROR("Failed to create SRv6 nexthop %s", m_key.to_string(false, true).c_str());
}
}
else
{
SWSS_LOG_INFO("Failed to get next hop %s, resolving neighbor",
m_key.to_string().c_str());
gNeighOrch->resolveNeighbor(m_key);
}
}

return nh_id;
Expand Down Expand Up @@ -570,14 +660,22 @@ NextHopGroupMember::~NextHopGroupMember()
{
SWSS_LOG_ENTER();

if (m_key.isSrv6NextHop() && gNeighOrch->hasNextHop(m_key) &&
!gNeighOrch->getNextHopRefCount(m_key))
{
if (!gSrv6Orch->removeSrv6NexthopWithoutVpn(m_key))
{
SWSS_LOG_ERROR("SRv6 Nexthop %s delete failed", m_key.to_string(false, true).c_str());
}
}
/*
* If the labeled next hop is unreferenced, remove it from NeighOrch as
* NhgOrch and RouteOrch are the ones controlling it's lifetime. They both
* watch over these labeled next hops, so it doesn't matter who created
* them as they're both doing the same checks before removing a labeled
* next hop.
*/
if (isLabeled() &&
else if (isLabeled() &&
gNeighOrch->hasNextHop(m_key) &&
(gNeighOrch->getNextHopRefCount(m_key) == 0))
{
Expand Down Expand Up @@ -824,6 +922,7 @@ bool NextHopGroup::syncMembers(const std::set<NextHopKey>& nh_keys)
*/
std::map<NextHopKey, sai_object_id_t> syncingMembers;

bool success = true;
for (const auto& nh_key : nh_keys)
{
NextHopGroupMember& nhgm = m_members.at(nh_key);
Expand All @@ -841,7 +940,8 @@ bool NextHopGroup::syncMembers(const std::set<NextHopKey>& nh_keys)
{
SWSS_LOG_WARN("Failed to get next hop %s in group %s",
nhgm.to_string().c_str(), to_string().c_str());
return false;
success = false;
continue;
}

/* If the neighbor's interface is down, skip from being syncd. */
Expand All @@ -868,7 +968,6 @@ bool NextHopGroup::syncMembers(const std::set<NextHopKey>& nh_keys)
* Go through the synced members and increment the Crm ref count for the
* successful ones.
*/
bool success = true;
for (const auto& mbr : syncingMembers)
{
/* Check that the returned member ID is valid. */
Expand Down Expand Up @@ -941,7 +1040,7 @@ bool NextHopGroup::update(const NextHopGroupKey& nhg_key)
/* If the member is updated, update it's weight. */
else
{
if (!mbr_it.second.updateWeight(new_nh_key_it->weight))
if (new_nh_key_it->weight && mbr_it.second.getWeight() != new_nh_key_it->weight && !mbr_it.second.updateWeight(new_nh_key_it->weight))
{
SWSS_LOG_WARN("Failed to update member %s weight", nh_key.to_string().c_str());
return false;
Expand Down
3 changes: 2 additions & 1 deletion orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ bool OrchDaemon::init()

vector<string> srv6_tables = {
APP_SRV6_SID_LIST_TABLE_NAME,
APP_SRV6_MY_SID_TABLE_NAME
APP_SRV6_MY_SID_TABLE_NAME,
APP_PIC_CONTEXT_TABLE_NAME
};
gSrv6Orch = new Srv6Orch(m_applDb, srv6_tables, gSwitchOrch, vrf_orch, gNeighOrch);
gDirectory.set(gSrv6Orch);
Expand Down
Loading
Loading