Skip to content

Commit afe2a0d

Browse files
kcudniklguohan
authored andcommitted
[vs]: Fix learn fdb events after fdb flush event (sonic-net#524)
Before this fix if flush event is received, vlan id in fdb_info was always set to zero, and it should be extracted from bv_id field in fdb_entry, this was causing to not find exact fdb entry in g_fdb_info_set and since those entries were always there, they were not "learned" again
1 parent d29760f commit afe2a0d

File tree

5 files changed

+160
-3
lines changed

5 files changed

+160
-3
lines changed

lib/src/sai_redis_fdb.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ sai_status_t internal_redis_flush_fdb_entries(
1919

2020
std::string key = str_object_type + ":" + sai_serialize_object_id(switch_id);
2121

22-
SWSS_LOG_DEBUG("flush key: %s, fields: %lu", key.c_str(), entry.size());
22+
SWSS_LOG_NOTICE("flush key: %s, fields: %lu", key.c_str(), entry.size());
2323

2424
if (g_record)
2525
{
@@ -76,7 +76,7 @@ sai_status_t internal_redis_flush_fdb_entries(
7676
recordLine("F|" + str_status);
7777
}
7878

79-
SWSS_LOG_DEBUG("flush status: %d", status);
79+
SWSS_LOG_NOTICE("flush status: %d", status);
8080

8181
return status;
8282
}

saiplayer/saiplayer.cpp

+90
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,76 @@ void performNotifySyncd(const std::string& request, const std::string response)
857857
// OK
858858
}
859859

860+
void performFdbFlush(
861+
_In_ const std::string& request,
862+
_In_ const std::string response)
863+
{
864+
SWSS_LOG_ENTER();
865+
866+
// 2017-05-13.20:47:24.883499|f|SAI_OBJECT_TYPE_FDB_FLUSH:oid:0x21000000000000|
867+
// 2017-05-13.20:47:24.883499|F|SAI_STATUS_SUCCESS
868+
869+
// timestamp|action|data
870+
auto r = swss::tokenize(request, '|');
871+
auto R = swss::tokenize(response, '|');
872+
873+
if (r[1] != "f" || R[1] != "F")
874+
{
875+
SWSS_LOG_THROW("invalid fdb flush request/response %s/%s", request.c_str(), response.c_str());
876+
}
877+
878+
if (r.size() > 3 && r[3].size() != 0)
879+
{
880+
SWSS_LOG_NOTICE("%zu %zu, %s", r.size(), r[3].size(), r[3].c_str());
881+
// TODO currently we support only flush fdb entries with no attributes
882+
SWSS_LOG_THROW("currently fdb flush supports only no attributes, but some given: %s", request.c_str());
883+
}
884+
885+
// objecttype:objectid (object id may contain ':')
886+
auto& data = r[2];
887+
auto start = data.find_first_of(":");
888+
auto str_object_type = data.substr(0, start);
889+
auto str_object_id = data.substr(start + 1);
890+
891+
sai_object_type_t ot = deserialize_object_type(str_object_type);
892+
893+
if (ot != SAI_OBJECT_TYPE_FDB_FLUSH)
894+
{
895+
SWSS_LOG_THROW("expected object type %s, but got: %s on %s",
896+
sai_serialize_object_type(SAI_OBJECT_TYPE_FDB_FLUSH).c_str(),
897+
str_object_type.c_str(),
898+
request.c_str());
899+
}
900+
901+
sai_object_id_t local_switch_id;
902+
sai_deserialize_object_id(str_object_id, local_switch_id);
903+
904+
if (sai_switch_id_query(local_switch_id) != local_switch_id)
905+
{
906+
SWSS_LOG_THROW("fdb flush object is not switch id: %s, switch_id_query: %s",
907+
str_object_id.c_str(),
908+
sai_serialize_object_id(sai_switch_id_query(local_switch_id)).c_str());
909+
}
910+
911+
auto switch_id = translate_local_to_redis(local_switch_id);
912+
913+
// TODO currently we support only flush fdb entries with no attributes
914+
sai_status_t status = sai_metadata_sai_fdb_api->flush_fdb_entries(switch_id, 0, NULL);
915+
916+
// check status
917+
sai_status_t expected_status;
918+
sai_deserialize_status(R[2], expected_status);
919+
920+
if (status != expected_status)
921+
{
922+
SWSS_LOG_THROW("fdb flush got status %s, but expecting: %s",
923+
sai_serialize_status(status).c_str(),
924+
R[2].c_str());
925+
}
926+
927+
// fdb flush OK
928+
}
929+
860930
std::vector<std::string> tokenize(
861931
_In_ std::string input,
862932
_In_ const std::string &delim)
@@ -1189,6 +1259,25 @@ int replay(int argc, char **argv)
11891259
performNotifySyncd(line, response);
11901260
}
11911261
continue;
1262+
1263+
case 'f':
1264+
{
1265+
std::string response;
1266+
1267+
do
1268+
{
1269+
// this line may be notification, we need to skip
1270+
if (!std::getline(infile, response))
1271+
{
1272+
SWSS_LOG_THROW("failed to read next file from file, previous: %s", line.c_str());
1273+
}
1274+
}
1275+
while (response[response.find_first_of("|") + 1] == 'n');
1276+
1277+
performFdbFlush(line, response);
1278+
}
1279+
continue;
1280+
11921281
case '@':
11931282
performSleep(line);
11941283
continue;
@@ -1217,6 +1306,7 @@ int replay(int argc, char **argv)
12171306
continue; // skip over query responses
12181307
case '#':
12191308
case 'n':
1309+
SWSS_LOG_INFO("skipping op %c line %s", op, line.c_str());
12201310
continue; // skip comment and notification
12211311

12221312
default:

syncd/syncd_notifications.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,23 @@ bool check_fdb_event_notification_data(
324324
return result;
325325
}
326326

327+
bool contains_fdb_flush_event(
328+
_In_ uint32_t count,
329+
_In_ const sai_fdb_event_notification_data_t *data)
330+
{
331+
SWSS_LOG_ENTER();
332+
333+
sai_mac_t mac = { 0, 0, 0, 0, 0, 0 };
334+
335+
for (uint32_t idx = 0; idx < count; idx++)
336+
{
337+
if (memcmp(mac, data[idx].fdb_entry.mac_address, sizeof(mac)) == 0)
338+
return true;
339+
}
340+
341+
return false;
342+
}
343+
327344
void process_on_fdb_event(
328345
_In_ uint32_t count,
329346
_In_ sai_fdb_event_notification_data_t *data)
@@ -468,6 +485,11 @@ void handle_fdb_event(
468485

469486
sai_deserialize_fdb_event_ntf(data, count, &fdbevent);
470487

488+
if (contains_fdb_flush_event(count, fdbevent))
489+
{
490+
SWSS_LOG_NOTICE("got fdb flush event: %s", data.c_str());
491+
}
492+
471493
process_on_fdb_event(count, fdbevent);
472494

473495
sai_deserialize_free_fdb_event_ntf(count, fdbevent);

vslib/src/sai_vs_fdb.cpp

+27-1
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,42 @@ sai_status_t internal_vs_flush_fdb_entries(
135135

136136
fdb_info_t fi;
137137

138+
// will set vlan to 0, we need to recreate that information
138139
memset(&fi, 0, sizeof(fi));
139140

141+
// If fdb entry has bv_id set to vlan object type then we can try to get vlan number from
142+
// that object and populate vlan_id in fdb_info. If bv_id is bridge object type then vlan
143+
// must be zero, since there can be only 1 (assuming) mac address on a given bridge.
144+
140145
sai_deserialize_fdb_entry(it->first, fi.fdb_entry);
141146

147+
if (sai_object_type_query(fi.fdb_entry.bv_id) == SAI_OBJECT_TYPE_VLAN)
148+
{
149+
sai_attribute_t attr;
150+
151+
attr.id = SAI_VLAN_ATTR_VLAN_ID;
152+
153+
sai_status_t status = vs_generic_get(SAI_OBJECT_TYPE_VLAN, fi.fdb_entry.bv_id, 1, &attr);
154+
155+
if (status != SAI_STATUS_SUCCESS)
156+
{
157+
SWSS_LOG_ERROR("failed to get vlan_id for vlan object: %s",
158+
sai_serialize_object_id(fi.fdb_entry.bv_id).c_str());
159+
160+
return SAI_STATUS_FAILURE;
161+
}
162+
163+
SWSS_LOG_INFO("got vlan id %d", attr.value.u16);
164+
165+
fi.vlan_id = attr.value.u16;
166+
}
167+
142168
auto fit = g_fdb_info_set.find(fi);
143169

144170
if (fit == g_fdb_info_set.end())
145171
{
146172
// this may happen if vlan is invalid
147-
SWSS_LOG_ERROR("failed to find fdb entry in info set: %s", it->first.c_str());
173+
SWSS_LOG_ERROR("failed to find fdb entry in info set: %s, learn for this MAC will be disabled", it->first.c_str());
148174
}
149175
else
150176
{

vslib/src/sai_vs_hostintf.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ void findBridgeVlanForPortVlan(
225225

226226
// iterate via all bridge ports to find match on port id
227227

228+
bool bv_id_set = false;
229+
228230
for (auto it = objectHash.begin(); it != objectHash.end(); ++it)
229231
{
230232
sai_object_id_t bpid;
@@ -289,6 +291,7 @@ void findBridgeVlanForPortVlan(
289291
sai_serialize_object_id(bridge_id).c_str(),
290292
attr.value.s32);
291293
bv_id = bridge_id;
294+
bv_id_set = true;
292295
}
293296
else
294297
{
@@ -315,13 +318,21 @@ void findBridgeVlanForPortVlan(
315318
if (vlan_id == attr.value.u16)
316319
{
317320
bv_id = vlan_oid;
321+
bv_id_set = true;
318322
break;
319323
}
320324
}
321325
}
322326

323327
break;
324328
}
329+
330+
if (!bv_id_set)
331+
{
332+
SWSS_LOG_WARN("failed to find bv_id for vlan %d and port_id %s",
333+
vlan_id,
334+
sai_serialize_object_id(port_id).c_str());
335+
}
325336
}
326337

327338
bool getLagFromPort(
@@ -541,6 +552,7 @@ void process_packet_for_fdb_event(
541552
return;
542553
}
543554

555+
// untagged port vlan (default is 1, but may change setting port attr)
544556
vlan_id = attr.value.u16;
545557
}
546558
}
@@ -586,10 +598,17 @@ void process_packet_for_fdb_event(
586598

587599
if (fi.fdb_entry.bv_id == SAI_NULL_OBJECT_ID)
588600
{
601+
SWSS_LOG_WARN("skipping mac learn for %s, since BV_ID was not found for mac",
602+
sai_serialize_fdb_entry(fi.fdb_entry).c_str());
603+
589604
// bridge was not found, skip mac learning
590605
return;
591606
}
592607

608+
SWSS_LOG_INFO("inserting to fdb_info set: %s, vid: %d",
609+
sai_serialize_fdb_entry(fi.fdb_entry).c_str(),
610+
fi.vlan_id);
611+
593612
g_fdb_info_set.insert(fi);
594613

595614
processFdbInfo(fi, SAI_FDB_EVENT_LEARNED);

0 commit comments

Comments
 (0)