Skip to content

Commit e658b64

Browse files
Pterosaurstcheng
authored andcommitted
[chassisorch]: Add everflow feature for chassis (#1024)
Signed-off-by: Ze Gan <[email protected]>
1 parent 5b13387 commit e658b64

File tree

6 files changed

+347
-2
lines changed

6 files changed

+347
-2
lines changed

orchagent/Makefile.am

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ orchagent_SOURCES = \
5252
dtelorch.cpp \
5353
flexcounterorch.cpp \
5454
watermarkorch.cpp \
55-
policerorch.cpp
55+
policerorch.cpp \
56+
chassisorch.cpp
5657

5758
orchagent_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
5859
orchagent_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)

orchagent/chassisorch.cpp

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "chassisorch.h"
2+
#include "routeorch.h"
3+
4+
ChassisOrch::ChassisOrch(
5+
DBConnector* cfgDb,
6+
DBConnector* applDb,
7+
const std::vector<std::string>& tableNames,
8+
VNetRouteOrch* vNetRouteOrch) :
9+
Orch(cfgDb, tableNames),
10+
m_passThroughRouteTable(applDb, APP_PASS_THROUGH_ROUTE_TABLE_NAME),
11+
m_vNetRouteOrch(vNetRouteOrch)
12+
{
13+
}
14+
15+
void ChassisOrch::update(SubjectType type, void* ctx)
16+
{
17+
SWSS_LOG_ENTER();
18+
VNetNextHopUpdate* updateInfo = reinterpret_cast<VNetNextHopUpdate*>(ctx);
19+
if (updateInfo->op == SET_COMMAND)
20+
{
21+
addRouteToPassThroughRouteTable(*updateInfo);
22+
}
23+
else
24+
{
25+
deleteRoutePassThroughRouteTable(*updateInfo);
26+
}
27+
}
28+
29+
void ChassisOrch::addRouteToPassThroughRouteTable(const VNetNextHopUpdate& update)
30+
{
31+
SWSS_LOG_ENTER();
32+
33+
std::vector<FieldValueTuple> fvVector;
34+
fvVector.emplace_back("redistribute", "true");
35+
fvVector.emplace_back("next_vrf_name", update.vnet);
36+
fvVector.emplace_back("next_hop_ip", update.nexthop.ips.to_string());
37+
fvVector.emplace_back("ifname", update.nexthop.ifname);
38+
fvVector.emplace_back("source", "CHASSIS_ORCH");
39+
const std::string everflow_route = IpPrefix(update.destination.to_string()).to_string();
40+
m_passThroughRouteTable.set(everflow_route, fvVector);
41+
}
42+
43+
void ChassisOrch::deleteRoutePassThroughRouteTable(const VNetNextHopUpdate& update)
44+
{
45+
SWSS_LOG_ENTER();
46+
const std::string everflow_route = IpPrefix(update.destination.to_string()).to_string();
47+
m_passThroughRouteTable.del(everflow_route);
48+
}
49+
50+
void ChassisOrch::doTask(Consumer &consumer)
51+
{
52+
SWSS_LOG_ENTER();
53+
54+
const std::string & tableName = consumer.getTableName();
55+
auto it = consumer.m_toSync.begin();
56+
while (it != consumer.m_toSync.end())
57+
{
58+
auto t = it->second;
59+
const std::string & op = kfvOp(t);
60+
const std::string & ip = kfvKey(t);
61+
62+
if (op == SET_COMMAND)
63+
{
64+
m_vNetRouteOrch->attach(this, ip);
65+
}
66+
else
67+
{
68+
m_vNetRouteOrch->detach(this, ip);
69+
}
70+
it = consumer.m_toSync.erase(it);
71+
}
72+
73+
}
74+

orchagent/chassisorch.h

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef SWSS_CHASSISORCH_H
2+
#define SWSS_CHASSISORCH_H
3+
4+
#include <map>
5+
#include <set>
6+
#include <string>
7+
#include <vector>
8+
9+
#include "dbconnector.h"
10+
#include "producerstatetable.h"
11+
#include "orch.h"
12+
#include "observer.h"
13+
#include "vnetorch.h"
14+
15+
class ChassisOrch : public Orch, public Observer
16+
{
17+
public:
18+
ChassisOrch(
19+
DBConnector* cfgDb,
20+
DBConnector *applDb,
21+
const std::vector<std::string> &tableNames,
22+
VNetRouteOrch * vNetRouteOrch);
23+
24+
private:
25+
26+
void update(SubjectType, void*);
27+
void addRouteToPassThroughRouteTable(const VNetNextHopUpdate& update);
28+
void deleteRoutePassThroughRouteTable(const VNetNextHopUpdate& update);
29+
30+
virtual void doTask(Consumer &consumer);
31+
32+
Table m_passThroughRouteTable;
33+
VNetRouteOrch* m_vNetRouteOrch;
34+
};
35+
36+
#endif

orchagent/orchdaemon.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#define SAI_SWITCH_ATTR_CUSTOM_RANGE_BASE SAI_SWITCH_ATTR_CUSTOM_RANGE_START
1010
#include "sairedis.h"
11+
#include "chassisorch.h"
1112

1213
using namespace std;
1314
using namespace swss;
@@ -112,6 +113,12 @@ bool OrchDaemon::init()
112113
VRFOrch *vrf_orch = new VRFOrch(m_applDb, APP_VRF_TABLE_NAME);
113114
gDirectory.set(vrf_orch);
114115

116+
const vector<string> chassis_frontend_tables = {
117+
CFG_PASS_THROUGH_ROUTE_TABLE_NAME,
118+
};
119+
ChassisOrch* chassis_frontend_orch = new ChassisOrch(m_configDb, m_applDb, chassis_frontend_tables, vnet_rt_orch);
120+
gDirectory.set(chassis_frontend_orch);
121+
115122
gIntfsOrch = new IntfsOrch(m_applDb, APP_INTF_TABLE_NAME, vrf_orch);
116123
gNeighOrch = new NeighOrch(m_applDb, APP_NEIGH_TABLE_NAME, gIntfsOrch);
117124
gRouteOrch = new RouteOrch(m_applDb, APP_ROUTE_TABLE_NAME, gNeighOrch);
@@ -225,6 +232,7 @@ bool OrchDaemon::init()
225232
m_orchList.push_back(gFdbOrch);
226233
m_orchList.push_back(mirror_orch);
227234
m_orchList.push_back(gAclOrch);
235+
m_orchList.push_back(chassis_frontend_orch);
228236
m_orchList.push_back(vrf_orch);
229237
m_orchList.push_back(vxlan_tunnel_orch);
230238
m_orchList.push_back(vxlan_tunnel_map_orch);

orchagent/vnetorch.cpp

+195
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <unordered_set>
66
#include <exception>
77
#include <inttypes.h>
8+
#include <algorithm>
89

910
#include "sai.h"
1011
#include "saiextensions.h"
@@ -1911,6 +1912,15 @@ bool VNetRouteOrch::handleRoutes(const Request& request)
19111912

19121913
SWSS_LOG_INFO("VNET-RT '%s' op '%s' for ip %s", vnet_name.c_str(),
19131914
op.c_str(), ip_pfx.to_string().c_str());
1915+
1916+
if (op == SET_COMMAND)
1917+
{
1918+
addRoute(vnet_name, ip_pfx, nh);
1919+
}
1920+
else
1921+
{
1922+
delRoute(ip_pfx);
1923+
}
19141924

19151925
if (vnet_orch_->isVnetExecVrf())
19161926
{
@@ -1924,6 +1934,191 @@ bool VNetRouteOrch::handleRoutes(const Request& request)
19241934
return true;
19251935
}
19261936

1937+
void VNetRouteOrch::attach(Observer* observer, const IpAddress& dstAddr)
1938+
{
1939+
SWSS_LOG_ENTER();
1940+
1941+
auto insert_result = next_hop_observers_.emplace(dstAddr, VNetNextHopObserverEntry());
1942+
auto observerEntry = insert_result.first;
1943+
/* Create a new observer entry if no current observer is observing this
1944+
* IP address */
1945+
if (insert_result.second)
1946+
{
1947+
/* Find the prefixes that cover the destination IP */
1948+
for (auto route : syncd_routes_)
1949+
{
1950+
if (route.first.isAddressInSubnet(dstAddr))
1951+
{
1952+
SWSS_LOG_INFO("Prefix %s covers destination address",
1953+
route.first.to_string().c_str());
1954+
1955+
observerEntry->second.routeTable.emplace(
1956+
route.first,
1957+
route.second
1958+
);
1959+
}
1960+
}
1961+
}
1962+
1963+
observerEntry->second.observers.push_back(observer);
1964+
1965+
auto bestRoute = observerEntry->second.routeTable.rbegin();
1966+
if (bestRoute != observerEntry->second.routeTable.rend())
1967+
{
1968+
SWSS_LOG_NOTICE("Attached next hop observer of route %s for destination IP %s",
1969+
bestRoute->first.to_string().c_str(),
1970+
dstAddr.to_string().c_str());
1971+
for (auto vnetEntry : bestRoute->second)
1972+
{
1973+
VNetNextHopUpdate update =
1974+
{
1975+
SET_COMMAND,
1976+
vnetEntry.first, // vnet name
1977+
dstAddr, // destination
1978+
bestRoute->first, // prefix
1979+
vnetEntry.second // nexthop
1980+
};
1981+
observer->update(SUBJECT_TYPE_NEXTHOP_CHANGE, reinterpret_cast<void*>(&update));
1982+
}
1983+
}
1984+
}
1985+
1986+
void VNetRouteOrch::detach(Observer* observer, const IpAddress& dstAddr)
1987+
{
1988+
SWSS_LOG_ENTER();
1989+
auto observerEntry = next_hop_observers_.find(dstAddr);
1990+
1991+
if (observerEntry == next_hop_observers_.end())
1992+
{
1993+
SWSS_LOG_ERROR("Failed to detach observer for %s. Entry not found.", dstAddr.to_string().c_str());
1994+
assert(false);
1995+
return;
1996+
}
1997+
1998+
auto iter = std::find(
1999+
observerEntry->second.observers.begin(),
2000+
observerEntry->second.observers.end(),
2001+
observer);
2002+
if (iter == observerEntry->second.observers.end())
2003+
{
2004+
SWSS_LOG_ERROR("Failed to detach observer for %s. Observer not found.", dstAddr.to_string().c_str());
2005+
assert(false);
2006+
return;
2007+
}
2008+
2009+
auto bestRoute = observerEntry->second.routeTable.rbegin();
2010+
if (bestRoute != observerEntry->second.routeTable.rend())
2011+
{
2012+
for (auto vnetEntry : bestRoute->second)
2013+
{
2014+
VNetNextHopUpdate update =
2015+
{
2016+
DEL_COMMAND,
2017+
vnetEntry.first, // vnet name
2018+
dstAddr, // destination
2019+
bestRoute->first, // prefix
2020+
vnetEntry.second // nexthop
2021+
};
2022+
observer->update(SUBJECT_TYPE_NEXTHOP_CHANGE, reinterpret_cast<void*>(&update));
2023+
}
2024+
}
2025+
next_hop_observers_.erase(observerEntry);
2026+
}
2027+
2028+
void VNetRouteOrch::addRoute(const std::string& vnet, const IpPrefix& ipPrefix, const nextHop& nh)
2029+
{
2030+
SWSS_LOG_ENTER();
2031+
for (auto& next_hop_observer : next_hop_observers_)
2032+
{
2033+
if (ipPrefix.isAddressInSubnet(next_hop_observer.first))
2034+
{
2035+
auto route_insert_result = next_hop_observer.second.routeTable.emplace(ipPrefix, VNetEntry());
2036+
2037+
auto vnet_result_result = route_insert_result.first->second.emplace(vnet, nh);
2038+
if (!vnet_result_result.second)
2039+
{
2040+
if (vnet_result_result.first->second.ips == nh.ips
2041+
&& vnet_result_result.first->second.ifname == nh.ifname)
2042+
{
2043+
continue;
2044+
}
2045+
vnet_result_result.first->second = nh;
2046+
}
2047+
2048+
// If the inserted route is the best route. (Table should not be empty. Because we inserted a new entry above)
2049+
if (route_insert_result.first == --next_hop_observer.second.routeTable.end())
2050+
{
2051+
VNetNextHopUpdate update =
2052+
{
2053+
SET_COMMAND,
2054+
vnet, // vnet name
2055+
next_hop_observer.first, // destination
2056+
ipPrefix, // prefix
2057+
nh // nexthop
2058+
};
2059+
for (auto& observer : next_hop_observer.second.observers)
2060+
{
2061+
observer->update(SUBJECT_TYPE_NEXTHOP_CHANGE, reinterpret_cast<void*>(&update));
2062+
}
2063+
}
2064+
}
2065+
}
2066+
syncd_routes_.emplace(ipPrefix, VNetEntry()).first->second[vnet] = nh;
2067+
}
2068+
2069+
void VNetRouteOrch::delRoute(const IpPrefix& ipPrefix)
2070+
{
2071+
SWSS_LOG_ENTER();
2072+
2073+
auto route_itr = syncd_routes_.find(ipPrefix);
2074+
if (route_itr == syncd_routes_.end())
2075+
{
2076+
SWSS_LOG_ERROR("Failed to find route %s.", ipPrefix.to_string().c_str());
2077+
assert(false);
2078+
return;
2079+
}
2080+
auto next_hop_observer = next_hop_observers_.begin();
2081+
while(next_hop_observer != next_hop_observers_.end())
2082+
{
2083+
if (ipPrefix.isAddressInSubnet(next_hop_observer->first))
2084+
{
2085+
auto itr = next_hop_observer->second.routeTable.find(ipPrefix);
2086+
if ( itr == next_hop_observer->second.routeTable.end())
2087+
{
2088+
SWSS_LOG_ERROR(
2089+
"Failed to find any ip(%s) belong to this route(%s).",
2090+
next_hop_observer->first.to_string().c_str(),
2091+
ipPrefix.to_string().c_str());
2092+
assert(false);
2093+
continue;
2094+
}
2095+
if (itr->second.empty())
2096+
{
2097+
continue;
2098+
}
2099+
for (auto& observer : next_hop_observer->second.observers)
2100+
{
2101+
VNetNextHopUpdate update = {
2102+
DEL_COMMAND,
2103+
itr->second.rbegin()->first, // vnet name
2104+
next_hop_observer->first, // destination
2105+
itr->first, // prefix
2106+
itr->second.rbegin()->second // nexthop
2107+
};
2108+
observer->update(SUBJECT_TYPE_NEXTHOP_CHANGE, reinterpret_cast<void*>(&update));
2109+
}
2110+
next_hop_observer->second.routeTable.erase(itr);
2111+
if (next_hop_observer->second.routeTable.empty())
2112+
{
2113+
next_hop_observer = next_hop_observers_.erase(next_hop_observer);
2114+
continue;
2115+
}
2116+
}
2117+
next_hop_observer++;
2118+
}
2119+
syncd_routes_.erase(route_itr);
2120+
}
2121+
19272122
bool VNetRouteOrch::handleTunnel(const Request& request)
19282123
{
19292124
SWSS_LOG_ENTER();

0 commit comments

Comments
 (0)