Skip to content

Commit 4495a5d

Browse files
zjswhhhprsunny
authored andcommitted
[ssw][ha] vnetorch supporting DPU live re-pairing (sonic-net#4042)
What I did Support route update from vnet tunnel route config change for custom_bfd monitoring. In DPU repairing scenario (to form HA sets), VNetOrch needs to support live update of endpoints, monitoring endpoints, primary and secondary groups. sign-off: Jing Zhang [email protected] Why I did it This change is required for DPU repair in HA. How I did it When there is a route config change (i.e. primary endpoint changes), pass a BFD state update with Init state to trigger the monitoring session creation & deletion, and route update. Notice that monitoring orch will pass Down and Up state to vnet orch.
1 parent 567b6bd commit 4495a5d

3 files changed

Lines changed: 363 additions & 49 deletions

File tree

orchagent/vnetorch.cpp

Lines changed: 187 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,13 +1052,21 @@ bool VNetRouteOrch::selectNextHopGroup(const string& vnet,
10521052
}
10531053
else
10541054
{
1055-
if (it_route->second.primary != nexthops_primary)
1055+
if (isCustomMonitorEndpointUpdated(vnet, ipPrefix, monitors))
10561056
{
10571057
setEndpointMonitor(vnet, monitors, nexthops_primary, monitoring, rx_monitor_timer, tx_monitor_timer, ipPrefix);
1058+
setEndpointMonitor(vnet, monitors, nexthops_secondary, monitoring, rx_monitor_timer, tx_monitor_timer, ipPrefix);
10581059
}
1059-
if (it_route->second.secondary != nexthops_secondary)
1060+
else
10601061
{
1061-
setEndpointMonitor(vnet, monitors, nexthops_secondary, monitoring, rx_monitor_timer, tx_monitor_timer, ipPrefix);
1062+
if (it_route->second.primary != nexthops_primary)
1063+
{
1064+
setEndpointMonitor(vnet, monitors, nexthops_primary, monitoring, rx_monitor_timer, tx_monitor_timer, ipPrefix);
1065+
}
1066+
if (it_route->second.secondary != nexthops_secondary)
1067+
{
1068+
setEndpointMonitor(vnet, monitors, nexthops_secondary, monitoring, rx_monitor_timer, tx_monitor_timer, ipPrefix);
1069+
}
10621070
}
10631071
nexthops_selected = it_route->second.nhg_key;
10641072
return true;
@@ -1173,6 +1181,16 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
11731181

11741182
if (op == SET_COMMAND)
11751183
{
1184+
bool custom_monitor_ep_updated = isCustomMonitorEndpointUpdated(vnet, ipPrefix, monitors);
1185+
std::map<NextHopKey, swss::IpAddress> origin_primary_monitors;
1186+
std::map<NextHopKey, swss::IpAddress> origin_secondary_monitors;
1187+
if (custom_monitor_ep_updated)
1188+
{
1189+
auto it_route = syncd_tunnel_routes_[vnet].find(ipPrefix);
1190+
getCustomMonitors(vnet, ipPrefix, it_route->second.primary, origin_primary_monitors);
1191+
getCustomMonitors(vnet, ipPrefix, it_route->second.secondary, origin_secondary_monitors);
1192+
}
1193+
11761194
sai_object_id_t nh_id = SAI_NULL_OBJECT_ID;
11771195
NextHopGroupKey active_nhg("", true);
11781196
if (!selectNextHopGroup(vnet, nexthops, nexthops_secondary, monitoring, rx_monitor_timer, tx_monitor_timer, ipPrefix, vrf_obj, active_nhg, monitors))
@@ -1250,63 +1268,73 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
12501268
}
12511269
bool route_updated = false;
12521270
bool priority_route_updated = false;
1253-
if (it_route != syncd_tunnel_routes_[vnet].end() &&
1254-
((monitoring == "" && it_route->second.nhg_key != nexthops) ||
1255-
((monitoring == VNET_MONITORING_TYPE_CUSTOM || monitoring == VNET_MONITORING_TYPE_CUSTOM_BFD) && (it_route->second.primary != nexthops || it_route->second.secondary != nexthops_secondary))))
1256-
{
1257-
route_updated = true;
1258-
NextHopGroupKey nhg = it_route->second.nhg_key;
1259-
if (monitoring == VNET_MONITORING_TYPE_CUSTOM || monitoring == VNET_MONITORING_TYPE_CUSTOM_BFD)
1260-
{
1261-
// if the previously active NHG is same as the newly created active NHG.case of primary secondary swap or
1262-
//when primary is active and secondary is changed or vice versa. In these cases we dont remove the NHG
1263-
// but only remove the monitors for the set which has changed.
1264-
if (it_route->second.primary != nexthops)
1265-
{
1266-
delEndpointMonitor(vnet, it_route->second.primary, ipPrefix);
1267-
}
1268-
if (it_route->second.secondary != nexthops_secondary)
1269-
{
1270-
delEndpointMonitor(vnet, it_route->second.secondary, ipPrefix);
1271-
}
1272-
if (monitor_info_[vnet][ipPrefix].empty())
1273-
{
1274-
monitor_info_[vnet].erase(ipPrefix);
1275-
}
1276-
priority_route_updated = true;
1271+
if (it_route != syncd_tunnel_routes_[vnet].end())
1272+
{
1273+
if (custom_monitor_ep_updated)
1274+
{
1275+
route_updated = true;
1276+
1277+
delEndpointMonitor(vnet, origin_primary_monitors, ipPrefix);
1278+
delEndpointMonitor(vnet, origin_secondary_monitors, ipPrefix);
12771279
}
1278-
else
1280+
else if ((monitoring == "" && it_route->second.nhg_key != nexthops) ||
1281+
((monitoring == VNET_MONITORING_TYPE_CUSTOM || monitoring == VNET_MONITORING_TYPE_CUSTOM_BFD) &&
1282+
(it_route->second.primary != nexthops || it_route->second.secondary != nexthops_secondary)))
12791283
{
1280-
// In case of updating an existing route, decrease the reference count for the previous nexthop group
1281-
if (--syncd_nexthop_groups_[vnet][nhg].ref_count == 0)
1284+
route_updated = true;
1285+
NextHopGroupKey nhg = it_route->second.nhg_key;
1286+
if (monitoring == VNET_MONITORING_TYPE_CUSTOM || monitoring == VNET_MONITORING_TYPE_CUSTOM_BFD)
12821287
{
1283-
if (nhg.getSize() > 1)
1288+
// if the previously active NHG is same as the newly created active NHG.case of primary secondary swap or
1289+
//when primary is active and secondary is changed or vice versa. In these cases we dont remove the NHG
1290+
// but only remove the monitors for the set which has changed.
1291+
if (it_route->second.primary != nexthops)
12841292
{
1285-
removeNextHopGroup(vnet, nhg, vrf_obj);
1293+
delEndpointMonitor(vnet, it_route->second.primary, ipPrefix);
12861294
}
1287-
else
1295+
if (it_route->second.secondary != nexthops_secondary)
1296+
{
1297+
delEndpointMonitor(vnet, it_route->second.secondary, ipPrefix);
1298+
}
1299+
if (monitor_info_[vnet][ipPrefix].empty())
12881300
{
1289-
syncd_nexthop_groups_[vnet].erase(nhg);
1290-
if(nhg.getSize() == 1)
1301+
monitor_info_[vnet].erase(ipPrefix);
1302+
}
1303+
priority_route_updated = true;
1304+
}
1305+
else
1306+
{
1307+
// In case of updating an existing route, decrease the reference count for the previous nexthop group
1308+
if (--syncd_nexthop_groups_[vnet][nhg].ref_count == 0)
1309+
{
1310+
if (nhg.getSize() > 1)
12911311
{
1292-
NextHopKey nexthop = *nhg.getNextHops().begin();
1293-
if (!isLocalEndpoint(vnet, nexthop.ip_address))
1312+
removeNextHopGroup(vnet, nhg, vrf_obj);
1313+
}
1314+
else
1315+
{
1316+
syncd_nexthop_groups_[vnet].erase(nhg);
1317+
if(nhg.getSize() == 1)
12941318
{
1295-
vrf_obj->removeTunnelNextHop(nexthop);
1319+
NextHopKey nexthop = *nhg.getNextHops().begin();
1320+
if (!isLocalEndpoint(vnet, nexthop.ip_address))
1321+
{
1322+
vrf_obj->removeTunnelNextHop(nexthop);
1323+
}
12961324
}
12971325
}
1326+
if (monitoring != VNET_MONITORING_TYPE_CUSTOM && monitoring != VNET_MONITORING_TYPE_CUSTOM_BFD)
1327+
{
1328+
delEndpointMonitor(vnet, nhg, ipPrefix);
1329+
}
12981330
}
1299-
if (monitoring != VNET_MONITORING_TYPE_CUSTOM && monitoring != VNET_MONITORING_TYPE_CUSTOM_BFD)
1331+
else
13001332
{
1301-
delEndpointMonitor(vnet, nhg, ipPrefix);
1333+
syncd_nexthop_groups_[vnet][nhg].tunnel_routes.erase(ipPrefix);
13021334
}
1335+
vrf_obj->removeRoute(ipPrefix);
1336+
vrf_obj->removeProfile(ipPrefix);
13031337
}
1304-
else
1305-
{
1306-
syncd_nexthop_groups_[vnet][nhg].tunnel_routes.erase(ipPrefix);
1307-
}
1308-
vrf_obj->removeRoute(ipPrefix);
1309-
vrf_obj->removeProfile(ipPrefix);
13101338
}
13111339
}
13121340
if (!profile.empty())
@@ -1323,11 +1351,13 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
13231351
syncd_tunnel_routes_[vnet][ipPrefix] = tunnel_route_entry;
13241352
syncd_nexthop_groups_[vnet][active_nhg].ref_count++;
13251353

1326-
if (priority_route_updated)
1354+
if (priority_route_updated || custom_monitor_ep_updated)
13271355
{
13281356
MonitorUpdate update;
1357+
update.monitoring_type = monitoring;
13291358
update.prefix = ipPrefix;
13301359
update.state = MONITOR_SESSION_STATE_UNKNOWN;
1360+
update.custom_bfd_state = SAI_BFD_SESSION_STATE_INIT;
13311361
update.vnet = vnet;
13321362
updateVnetTunnelCustomMonitor(update);
13331363
return true;
@@ -2203,6 +2233,11 @@ void VNetRouteOrch::removeMonitoringSession(const string& vnet, const NextHopKey
22032233
}
22042234

22052235
monitor_info_[vnet][ipPrefix].erase(monitor_addr);
2236+
2237+
if (monitor_info_[vnet][ipPrefix].empty())
2238+
{
2239+
monitor_info_[vnet].erase(ipPrefix);
2240+
}
22062241
}
22072242

22082243
void VNetRouteOrch::setEndpointMonitor(const string& vnet, const map<NextHopKey, IpAddress>& monitors, NextHopGroupKey& nexthops, const string& monitoring, const int32_t rx_monitor_timer, const int32_t tx_monitor_timer, IpPrefix& ipPrefix)
@@ -2299,6 +2334,43 @@ void VNetRouteOrch::delEndpointMonitor(const string& vnet, NextHopGroupKey& next
22992334
}
23002335
}
23012336

2337+
void VNetRouteOrch::delEndpointMonitor(const string& vnet, const std::map<NextHopKey, IpAddress>& monitors, IpPrefix& ipPrefix)
2338+
{
2339+
SWSS_LOG_ENTER();
2340+
2341+
bool is_custom_monitoring = false;
2342+
if (monitor_info_[vnet].find(ipPrefix) != monitor_info_[vnet].end())
2343+
{
2344+
is_custom_monitoring = true;
2345+
}
2346+
for(auto monitor : monitors)
2347+
{
2348+
NextHopKey nhk = monitor.first;
2349+
IpAddress monitor_ip = monitor.second;
2350+
if (is_custom_monitoring)
2351+
{
2352+
if (monitor_info_[vnet][ipPrefix].find(monitor_ip) != monitor_info_[vnet][ipPrefix].end() &&
2353+
monitor_info_[vnet][ipPrefix][monitor_ip].endpoint == nhk)
2354+
{
2355+
if (--monitor_info_[vnet][ipPrefix][monitor_ip].ref_count == 0)
2356+
{
2357+
removeMonitoringSession(vnet, monitor_info_[vnet][ipPrefix][monitor_ip].endpoint, monitor_ip, ipPrefix);
2358+
}
2359+
}
2360+
}
2361+
else
2362+
{
2363+
if (nexthop_info_[vnet].find(nhk.ip_address) != nexthop_info_[vnet].end())
2364+
{
2365+
if (--nexthop_info_[vnet][nhk.ip_address].ref_count == 0)
2366+
{
2367+
removeBfdSession(vnet, nhk, monitor_ip);
2368+
}
2369+
}
2370+
}
2371+
}
2372+
}
2373+
23022374
void VNetRouteOrch::updateCustomBfdState(const IpAddress& monitoring_ip, const string& state)
23032375
{
23042376
SWSS_LOG_ENTER();
@@ -2321,7 +2393,8 @@ void VNetRouteOrch::updateCustomBfdState(const IpAddress& monitoring_ip, const s
23212393
}
23222394
else
23232395
{
2324-
SWSS_LOG_WARN("Unknown BFD state: %s", state.c_str());
2396+
/* VNetRouteOrch only processes Up/Down states from MonitorOrch */
2397+
SWSS_LOG_DEBUG("Ignoring BFD state: %s", state.c_str());
23252398
return;
23262399
}
23272400

@@ -2812,7 +2885,15 @@ void VNetRouteOrch::updateVnetTunnelCustomMonitor(const MonitorUpdate& update)
28122885

28132886
if(monitoring_type == VNET_MONITORING_TYPE_CUSTOM_BFD)
28142887
{
2815-
monitor_info_[vnet][prefix][monitor].custom_bfd_state = custom_bfd_state;
2888+
if (custom_bfd_state == SAI_BFD_SESSION_STATE_INIT)
2889+
{
2890+
updateRoute = true;
2891+
config_update = true;
2892+
}
2893+
else
2894+
{
2895+
monitor_info_[vnet][prefix][monitor].custom_bfd_state = custom_bfd_state;
2896+
}
28162897
}
28172898

28182899
auto route = syncd_tunnel_routes_[vnet].find(prefix);
@@ -3329,6 +3410,63 @@ bool VNetRouteOrch::isPartiallyLocal(const std::vector<swss::IpAddress>& ip_list
33293410
return !(all_true || all_false);
33303411
}
33313412

3413+
bool VNetRouteOrch::isCustomMonitorEndpointUpdated(const string& vnet, IpPrefix& ipPrefix,
3414+
const std::map<NextHopKey, swss::IpAddress>& monitors)
3415+
{
3416+
SWSS_LOG_ENTER();
3417+
3418+
if (monitor_info_.find(vnet) == monitor_info_.end() ||
3419+
monitor_info_[vnet].find(ipPrefix) == monitor_info_[vnet].end())
3420+
{
3421+
return false;
3422+
}
3423+
3424+
// If the nh endpoint exists in the monitor_info map but the monitor ip is different, then return true.
3425+
// Note that the key of monitor_info is monitoring endpoint ip address, while monitors is nexthop key
3426+
// to monitor endpoint ip mapping.
3427+
bool monitor_endpoint_updated = false;
3428+
for (auto it = monitor_info_[vnet][ipPrefix].begin(); it != monitor_info_[vnet][ipPrefix].end(); it++)
3429+
{
3430+
if (it->second.monitoring_type != VNET_MONITORING_TYPE_CUSTOM_BFD)
3431+
{
3432+
continue;
3433+
}
3434+
3435+
if (monitors.find(it->second.endpoint) != monitors.end() &&
3436+
it->first != monitors.at(it->second.endpoint))
3437+
{
3438+
monitor_endpoint_updated = true;
3439+
3440+
SWSS_LOG_NOTICE("Custom monitor endpoint updated for vnet %s, prefix %s, old monitor %s, new monitor %s",
3441+
vnet.c_str(), ipPrefix.to_string().c_str(),
3442+
it->first.to_string().c_str(),
3443+
monitors.at(it->second.endpoint).to_string().c_str());
3444+
3445+
}
3446+
}
3447+
3448+
return monitor_endpoint_updated;
3449+
}
3450+
3451+
void VNetRouteOrch::getCustomMonitors(const string& vnet, const IpPrefix& ipPrefix, const NextHopGroupKey& nexthops,
3452+
std::map<NextHopKey, swss::IpAddress>& monitors)
3453+
{
3454+
if (monitor_info_.find(vnet) != monitor_info_.end() && monitor_info_[vnet].find(ipPrefix) != monitor_info_[vnet].end())
3455+
{
3456+
for (auto nhk:nexthops.getNextHops())
3457+
{
3458+
for (const auto& monitor : monitor_info_[vnet][ipPrefix])
3459+
{
3460+
if (monitor.second.endpoint == nhk && (monitor.second.monitoring_type == VNET_MONITORING_TYPE_CUSTOM ||
3461+
monitor.second.monitoring_type == VNET_MONITORING_TYPE_CUSTOM_BFD))
3462+
{
3463+
monitors[nhk] = monitor.first;
3464+
break;
3465+
}
3466+
}
3467+
}
3468+
}
3469+
}
33323470

33333471
VNetCfgRouteOrch::VNetCfgRouteOrch(DBConnector *db, DBConnector *appDb, vector<string> &tableNames)
33343472
: Orch(db, tableNames),

orchagent/vnetorch.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,12 @@ class VNetRouteOrch : public Orch2, public Subject, public Observer
540540
const string& monitoring, const int32_t rx_monitor_timer, const int32_t tx_monitor_timer,
541541
IpPrefix& ipPrefix);
542542
void delEndpointMonitor(const string& vnet, NextHopGroupKey& nexthops, IpPrefix& ipPrefix);
543+
void delEndpointMonitor(const string& vnet, const std::map<NextHopKey, IpAddress>& monitors, IpPrefix& ipPrefix);
544+
545+
bool isCustomMonitorEndpointUpdated(const string& vnet, IpPrefix& ipPrefix,
546+
const std::map<NextHopKey, IpAddress>& monitors);
547+
void getCustomMonitors(const string& vnet, const IpPrefix& ipPrefix, const NextHopGroupKey& nexthops, std::map<NextHopKey, IpAddress>& monitors);
548+
543549
void postRouteState(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops, string& profile);
544550
void removeRouteState(const string& vnet, IpPrefix& ipPrefix);
545551
void addRouteAdvertisement(IpPrefix& ipPrefix, string& profile);

0 commit comments

Comments
 (0)