Skip to content

Commit f7fd7bd

Browse files
committed
Fix TrunkUtils.cpp A VLAN left with no ports must be dropped; otherwise it diverges between cold boot and warmboot
1 parent 9858da9 commit f7fd7bd

1 file changed

Lines changed: 66 additions & 1 deletion

File tree

fboss/agent/test/TrunkUtils.cpp

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,64 @@ cfg::AggregatePortMember makePortMember(int32_t port, cfg::LacpPortRate rate) {
2626
return aggMember;
2727
}
2828

29+
namespace {
30+
// A VLAN left with no ports must be dropped; otherwise it diverges between cold
31+
// boot and warmboot.
32+
void removeUnreferencedVlans(
33+
cfg::SwitchConfig* config,
34+
const std::set<int32_t>& memberOldVlans,
35+
int32_t aggVlan) {
36+
// TODO:remove this once cisco fixes the LAG vlan removal issue
37+
bool isCiscoAsic = false;
38+
for (const auto& [_, switchInfo] :
39+
*config->switchSettings()->switchIdToSwitchInfo()) {
40+
auto asicType = *switchInfo.asicType();
41+
if (asicType == cfg::AsicType::ASIC_TYPE_EBRO ||
42+
asicType == cfg::AsicType::ASIC_TYPE_YUBA ||
43+
asicType == cfg::AsicType::ASIC_TYPE_P200 ||
44+
asicType == cfg::AsicType::ASIC_TYPE_GARONNE ||
45+
asicType == cfg::AsicType::ASIC_TYPE_G202X) {
46+
isCiscoAsic = true;
47+
break;
48+
}
49+
}
50+
if (isCiscoAsic) {
51+
return;
52+
}
53+
54+
std::set<int32_t> stillReferenced;
55+
for (const auto& vlanPort : *config->vlanPorts()) {
56+
stillReferenced.insert(vlanPort.vlanID().value());
57+
}
58+
59+
for (auto oldVlan : memberOldVlans) {
60+
if (oldVlan == aggVlan || stillReferenced.contains(oldVlan) ||
61+
(oldVlan == *config->defaultVlan())) {
62+
continue;
63+
}
64+
65+
auto& vlans = *config->vlans();
66+
vlans.erase(
67+
std::remove_if(
68+
vlans.begin(),
69+
vlans.end(),
70+
[&](const auto& v) { return v.id().value() == oldVlan; }),
71+
vlans.end());
72+
73+
auto& intfs = *config->interfaces();
74+
intfs.erase(
75+
std::remove_if(
76+
intfs.begin(),
77+
intfs.end(),
78+
[&](const auto& i) {
79+
return i.type().value() == cfg::InterfaceType::VLAN &&
80+
i.vlanID().value() == oldVlan;
81+
}),
82+
intfs.end());
83+
}
84+
}
85+
} // namespace
86+
2987
void addAggPort(
3088
int key,
3189
const std::vector<int32_t>& ports,
@@ -54,15 +112,22 @@ void addAggPort(
54112
// Set VLAN for all members to be the same
55113
std::set<uint32_t> memberPorts(ports.begin(), ports.end());
56114
std::optional<int32_t> aggVlan;
115+
std::set<int32_t> memberOldVlans;
57116
for (auto& vlanPort : *config->vlanPorts()) {
58117
if (memberPorts.contains(vlanPort.logicalPort().value())) {
118+
int32_t oldVlan = vlanPort.vlanID().value();
119+
memberOldVlans.insert(oldVlan);
59120
if (!aggVlan) {
60-
aggVlan = vlanPort.vlanID().value();
121+
aggVlan = oldVlan;
61122
}
62123
vlanPort.vlanID() = *aggVlan;
63124
}
64125
}
65126

127+
if (aggVlan.has_value()) {
128+
removeUnreferencedVlans(config, memberOldVlans, *aggVlan);
129+
}
130+
66131
if (aggregatePortType == cfg::AggregatePortType::LAG_PORT) {
67132
// Set ingress VLAN for all members to be the same
68133
for (auto& port : *config->ports()) {

0 commit comments

Comments
 (0)