Skip to content

Commit ca28572

Browse files
Yakiv-Huryklolyu
authored andcommitted
[vnetorch] [vxlanorch] fix a set of memory usage issues (#2352)
* [vnetorch] fix use-after-free in removeBfdSession() * using a copy of monitor ip instead of a reference since the reference gets invalidated after the endpoint is erased Signed-off-by: Yakiv Huryk <yhuryk@nvidia.com> Signed-off-by: Longxiang Lyu <lolv@microsoft.com>
1 parent 1aaccd6 commit ca28572

File tree

5 files changed

+62
-13
lines changed

5 files changed

+62
-13
lines changed

orchagent/muxorch.cpp

+36-3
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,8 @@ static bool remove_nh_tunnel(sai_object_id_t nh_id, IpAddress& ipAddr)
351351
return true;
352352
}
353353

354-
MuxCable::MuxCable(string name, IpPrefix& srv_ip4, IpPrefix& srv_ip6, IpAddress peer_ip)
355-
:mux_name_(name), srv_ip4_(srv_ip4), srv_ip6_(srv_ip6), peer_ip4_(peer_ip)
354+
MuxCable::MuxCable(string name, IpPrefix& srv_ip4, IpPrefix& srv_ip6, IpAddress peer_ip, std::set<IpAddress> skip_neighbors)
355+
:mux_name_(name), srv_ip4_(srv_ip4), srv_ip6_(srv_ip6), peer_ip4_(peer_ip), skip_neighbors_(skip_neighbors)
356356
{
357357
mux_orch_ = gDirectory.get<MuxOrch*>();
358358
mux_cb_orch_ = gDirectory.get<MuxCableOrch*>();
@@ -534,6 +534,11 @@ bool MuxCable::nbrHandler(bool enable, bool update_rt)
534534
void MuxCable::updateNeighbor(NextHopKey nh, bool add)
535535
{
536536
sai_object_id_t tnh = mux_orch_->getNextHopTunnelId(MUX_TUNNEL, peer_ip4_);
537+
if (add && skip_neighbors_.count(nh.ip_address) != 0)
538+
{
539+
SWSS_LOG_NOTICE("Skip update neighbor %s on %s", nh.ip_address.to_string().c_str(), nh.alias.c_str());
540+
return;
541+
}
537542
nbr_handler_->update(nh, tnh, add, state_);
538543
if (add)
539544
{
@@ -1208,9 +1213,37 @@ bool MuxOrch::handleMuxCfg(const Request& request)
12081213
auto srv_ip = request.getAttrIpPrefix("server_ipv4");
12091214
auto srv_ip6 = request.getAttrIpPrefix("server_ipv6");
12101215

1216+
std::set<IpAddress> skip_neighbors;
1217+
std::string cable_type = "active-standby";
1218+
12111219
const auto& port_name = request.getKeyString(0);
12121220
auto op = request.getOperation();
12131221

1222+
for (const auto &name : request.getAttrFieldNames())
1223+
{
1224+
if (name == "soc_ipv4")
1225+
{
1226+
auto soc_ip = request.getAttrIpPrefix("soc_ipv4");
1227+
SWSS_LOG_NOTICE("%s: %s was added to ignored neighbor list", port_name.c_str(), soc_ip.getIp().to_string().c_str());
1228+
skip_neighbors.insert(soc_ip.getIp());
1229+
}
1230+
else if (name == "soc_ipv6")
1231+
{
1232+
auto soc_ip6 = request.getAttrIpPrefix("soc_ipv6");
1233+
SWSS_LOG_NOTICE("%s: %s was added to ignored neighbor list", port_name.c_str(), soc_ip6.getIp().to_string().c_str());
1234+
skip_neighbors.insert(soc_ip6.getIp());
1235+
}
1236+
else if (name == "cable_type")
1237+
{
1238+
cable_type = request.getAttrString("cable_type");
1239+
}
1240+
}
1241+
1242+
if (cable_type != "active-active")
1243+
{
1244+
skip_neighbors.clear();
1245+
}
1246+
12141247
if (op == SET_COMMAND)
12151248
{
12161249
if(isMuxExists(port_name))
@@ -1226,7 +1259,7 @@ bool MuxOrch::handleMuxCfg(const Request& request)
12261259
}
12271260

12281261
mux_cable_tb_[port_name] = std::make_unique<MuxCable>
1229-
(MuxCable(port_name, srv_ip, srv_ip6, mux_peer_switch_));
1262+
(MuxCable(port_name, srv_ip, srv_ip6, mux_peer_switch_, skip_neighbors));
12301263

12311264
SWSS_LOG_NOTICE("Mux entry for port '%s' was added", port_name.c_str());
12321265
}

orchagent/muxorch.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class MuxNbrHandler
7676
class MuxCable
7777
{
7878
public:
79-
MuxCable(string name, IpPrefix& srv_ip4, IpPrefix& srv_ip6, IpAddress peer_ip);
79+
MuxCable(string name, IpPrefix& srv_ip4, IpPrefix& srv_ip6, IpAddress peer_ip, std::set<IpAddress> skip_neighbors);
8080

8181
bool isActive() const
8282
{
@@ -115,6 +115,8 @@ class MuxCable
115115
IpPrefix srv_ip4_, srv_ip6_;
116116
IpAddress peer_ip4_;
117117

118+
std::set<IpAddress> skip_neighbors_;
119+
118120
MuxOrch *mux_orch_;
119121
MuxCableOrch *mux_cb_orch_;
120122
MuxStateOrch *mux_state_orch_;
@@ -132,6 +134,7 @@ const request_description_t mux_cfg_request_description = {
132134
{ "server_ipv6", REQ_T_IP_PREFIX },
133135
{ "address_ipv4", REQ_T_IP },
134136
{ "soc_ipv4", REQ_T_IP_PREFIX },
137+
{ "soc_ipv6", REQ_T_IP_PREFIX },
135138
{ "cable_type", REQ_T_STRING },
136139
},
137140
{ }

orchagent/vnetorch.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,8 @@ void VNetRouteOrch::delEndpointMonitor(const string& vnet, NextHopGroupKey& next
16021602
if (nexthop_info_[vnet].find(ip) != nexthop_info_[vnet].end()) {
16031603
if (--nexthop_info_[vnet][ip].ref_count == 0)
16041604
{
1605-
removeBfdSession(vnet, nhk, nexthop_info_[vnet][ip].monitor_addr);
1605+
IpAddress monitor_addr = nexthop_info_[vnet][ip].monitor_addr;
1606+
removeBfdSession(vnet, nhk, monitor_addr);
16061607
}
16071608
}
16081609
}

orchagent/vxlanorch.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1110,13 +1110,14 @@ void VxlanTunnel::updateRemoteEndPointIpRef(const std::string remote_vtep, bool
11101110
it->second.ip_refcnt++;
11111111
}
11121112
SWSS_LOG_DEBUG("Incrementing remote end point %s reference to %d", remote_vtep.c_str(),
1113-
it->second.ip_refcnt);
1113+
tnl_users_[remote_vtep].ip_refcnt);
11141114
}
11151115
else
11161116
{
11171117
if (it == tnl_users_.end())
11181118
{
11191119
SWSS_LOG_ERROR("Cannot decrement ref. End point not referenced %s", remote_vtep.c_str());
1120+
return;
11201121
}
11211122
it->second.ip_refcnt--;
11221123

tests/test_mux.py

+18-7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class TestMuxTunnelBase(object):
2727

2828
SERV1_IPV4 = "192.168.0.100"
2929
SERV1_IPV6 = "fc02:1000::100"
30+
SERV1_SOC_IPV4 = "192.168.0.102"
3031
SERV2_IPV4 = "192.168.0.101"
3132
SERV2_IPV6 = "fc02:1000::101"
3233
IPV4_MASK = "/32"
@@ -74,7 +75,12 @@ def create_vlan_interface(self, confdb, asicdb, dvs):
7475

7576
def create_mux_cable(self, confdb):
7677

77-
fvs = { "server_ipv4":self.SERV1_IPV4+self.IPV4_MASK, "server_ipv6":self.SERV1_IPV6+self.IPV6_MASK }
78+
fvs = {
79+
"server_ipv4":self.SERV1_IPV4 + self.IPV4_MASK,
80+
"server_ipv6":self.SERV1_IPV6 + self.IPV6_MASK,
81+
"soc_ipv4": self.SERV1_SOC_IPV4 + self.IPV4_MASK,
82+
"cable_type": "active-active"
83+
}
7884
confdb.create_entry(self.CONFIG_MUX_CABLE, "Ethernet0", fvs)
7985

8086
fvs = { "server_ipv4":self.SERV2_IPV4+self.IPV4_MASK, "server_ipv6":self.SERV2_IPV6+self.IPV6_MASK }
@@ -201,6 +207,9 @@ def create_and_test_neighbor(self, confdb, appdb, asicdb, dvs, dvs_route):
201207
self.add_neighbor(dvs, self.SERV1_IPV6, "00:00:00:00:00:01", True)
202208
srv1_v6 = self.check_neigh_in_asic_db(asicdb, self.SERV1_IPV6, 3)
203209

210+
self.add_neighbor(dvs, self.SERV1_SOC_IPV4, "00:00:00:00:00:01")
211+
srv1_soc_v4 = self.check_neigh_in_asic_db(asicdb, self.SERV1_SOC_IPV4, 4)
212+
204213
existing_keys = asicdb.get_keys(self.ASIC_NEIGH_TABLE)
205214

206215
self.add_neighbor(dvs, self.SERV2_IPV4, "00:00:00:00:00:02")
@@ -212,21 +221,23 @@ def create_and_test_neighbor(self, confdb, appdb, asicdb, dvs, dvs_route):
212221
dvs_route.check_asicdb_route_entries([self.SERV2_IPV4+self.IPV4_MASK, self.SERV2_IPV6+self.IPV6_MASK])
213222

214223
# The first standby route also creates as tunnel Nexthop
215-
self.check_tnl_nexthop_in_asic_db(asicdb, 3)
224+
self.check_tnl_nexthop_in_asic_db(asicdb, 4)
216225

217226
# Change state to Standby. This will delete Neigh and add Route
218227
self.set_mux_state(appdb, "Ethernet0", "standby")
219228

220229
asicdb.wait_for_deleted_entry(self.ASIC_NEIGH_TABLE, srv1_v4)
221230
asicdb.wait_for_deleted_entry(self.ASIC_NEIGH_TABLE, srv1_v6)
222231
dvs_route.check_asicdb_route_entries([self.SERV1_IPV4+self.IPV4_MASK, self.SERV1_IPV6+self.IPV6_MASK])
232+
self.check_neigh_in_asic_db(asicdb, self.SERV1_SOC_IPV4, 2)
233+
dvs_route.check_asicdb_deleted_route_entries([self.SERV1_SOC_IPV4+self.IPV4_MASK])
223234

224235
# Change state to Active. This will add Neigh and delete Route
225236
self.set_mux_state(appdb, "Ethernet4", "active")
226237

227238
dvs_route.check_asicdb_deleted_route_entries([self.SERV2_IPV4+self.IPV4_MASK, self.SERV2_IPV6+self.IPV6_MASK])
228-
self.check_neigh_in_asic_db(asicdb, self.SERV2_IPV4, 3)
229-
self.check_neigh_in_asic_db(asicdb, self.SERV2_IPV6, 3)
239+
self.check_neigh_in_asic_db(asicdb, self.SERV2_IPV4, 4)
240+
self.check_neigh_in_asic_db(asicdb, self.SERV2_IPV6, 4)
230241

231242

232243
def create_and_test_fdb(self, appdb, asicdb, dvs, dvs_route):
@@ -244,7 +255,7 @@ def create_and_test_fdb(self, appdb, asicdb, dvs, dvs_route):
244255
self.add_neighbor(dvs, ip_2, "00:00:00:00:00:12", True)
245256

246257
# ip_1 is on Active Mux, hence added to Host table
247-
self.check_neigh_in_asic_db(asicdb, ip_1, 4)
258+
self.check_neigh_in_asic_db(asicdb, ip_1, 5)
248259

249260
# ip_2 is on Standby Mux, hence added to Route table
250261
dvs_route.check_asicdb_route_entries([ip_2+self.IPV6_MASK])
@@ -260,7 +271,7 @@ def create_and_test_fdb(self, appdb, asicdb, dvs, dvs_route):
260271

261272
# ip_2 moved to active Mux, hence remove from Route table
262273
dvs_route.check_asicdb_deleted_route_entries([ip_2+self.IPV6_MASK])
263-
self.check_neigh_in_asic_db(asicdb, ip_2, 4)
274+
self.check_neigh_in_asic_db(asicdb, ip_2, 5)
264275

265276
# Simulate FDB aging out test case
266277
ip_3 = "192.168.0.200"
@@ -783,7 +794,7 @@ def test_Peer(self, dvs, testlog, setup):
783794

784795
self.create_and_test_peer(db, asicdb, "peer", "1.1.1.1", "10.1.0.32", encap_tc_to_dscp_map_id, encap_tc_to_queue_map_id)
785796

786-
def test_Neighbor(self, dvs, dvs_route, testlog):
797+
def test_Neighbor_aaa(self, dvs, dvs_route, testlog):
787798
""" test Neighbor entries and mux state change """
788799

789800
confdb = dvs.get_config_db()

0 commit comments

Comments
 (0)