Skip to content

Commit 76f9b4b

Browse files
Merge pull request #4087 from divyagayathri-hcl/5_multicast
[P4Orch] Implement functions to update multicast router interface table entries.
2 parents b60191c + 69e09ff commit 76f9b4b

File tree

2 files changed

+794
-35
lines changed

2 files changed

+794
-35
lines changed

orchagent/p4orch/l3_multicast_manager.cpp

Lines changed: 269 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ namespace p4orch {
3939

4040
namespace {
4141

42+
void fillStatusArrayWithNotExecuted(std::vector<ReturnCode>& array,
43+
size_t startIndex) {
44+
for (size_t i = startIndex; i < array.size(); ++i) {
45+
array[i] = ReturnCode(StatusCode::SWSS_RC_NOT_EXECUTED);
46+
}
47+
}
48+
4249
// Create the vector of SAI attributes for creating a new RIF object.
4350
ReturnCodeOr<std::vector<sai_attribute_t>> prepareRifSaiAttrs(
4451
const P4MulticastRouterInterfaceEntry& multicast_router_interface_entry) {
@@ -288,8 +295,22 @@ ReturnCode L3MulticastManager::createRouterInterface(
288295

289296
ReturnCode L3MulticastManager::deleteRouterInterface(const std::string& rif_key,
290297
sai_object_id_t rif_oid) {
291-
return ReturnCode(StatusCode::SWSS_RC_UNIMPLEMENTED)
292-
<< "L3MulticastManager::deleteRouterInterface is not implemented";
298+
SWSS_LOG_ENTER();
299+
// Confirm we have a RIF to be deleted.
300+
if (!m_p4OidMapper->existsOID(SAI_OBJECT_TYPE_ROUTER_INTERFACE, rif_key)) {
301+
LOG_ERROR_AND_RETURN(
302+
ReturnCode(StatusCode::SWSS_RC_INTERNAL)
303+
<< "Router interface to be deleted by multicast router interface table "
304+
<< QuotedVar(rif_key) << " does not exist in the centralized map");
305+
}
306+
auto sai_status = sai_router_intfs_api->remove_router_interface(rif_oid);
307+
if (sai_status != SAI_STATUS_SUCCESS) {
308+
LOG_ERROR_AND_RETURN(
309+
ReturnCode(sai_status)
310+
<< "Failed to remove router interface for multicast router interface "
311+
<< "table: " << QuotedVar(rif_key).c_str());
312+
}
313+
return ReturnCode();
293314
}
294315

295316
ReturnCode L3MulticastManager::createMulticastGroup(
@@ -322,6 +343,7 @@ std::vector<ReturnCode> L3MulticastManager::addMulticastRouterInterfaceEntries(
322343
SWSS_LOG_ENTER();
323344

324345
std::vector<ReturnCode> statuses(entries.size());
346+
fillStatusArrayWithNotExecuted(statuses, 0);
325347
for (size_t i = 0; i < entries.size(); ++i) {
326348
auto& entry = entries[i];
327349

@@ -335,9 +357,6 @@ std::vector<ReturnCode> L3MulticastManager::addMulticastRouterInterfaceEntries(
335357
createRouterInterface(rif_key, entry, &rif_oid);
336358
statuses[i] = create_status;
337359
if (!create_status.ok()) {
338-
for (size_t j = i + 1; j < entries.size(); ++j) {
339-
statuses[j] = ReturnCode(StatusCode::SWSS_RC_NOT_EXECUTED);
340-
}
341360
break;
342361
}
343362

@@ -365,21 +384,256 @@ std::vector<ReturnCode> L3MulticastManager::addMulticastRouterInterfaceEntries(
365384
std::vector<ReturnCode>
366385
L3MulticastManager::updateMulticastRouterInterfaceEntries(
367386
std::vector<P4MulticastRouterInterfaceEntry>& entries) {
368-
std::vector<ReturnCode> rv;
369-
rv.push_back(ReturnCode(StatusCode::SWSS_RC_UNIMPLEMENTED)
370-
<< "L3MulticastManager::updateMulticastRouterInterfaceEntries "
371-
<< "is not implemented");
372-
return rv;
387+
SWSS_LOG_ENTER();
388+
std::vector<ReturnCode> statuses(entries.size());
389+
fillStatusArrayWithNotExecuted(statuses, 0);
390+
391+
for (size_t i = 0; i < entries.size(); ++i) {
392+
auto& entry = entries[i];
393+
auto* old_entry_ptr = getMulticastRouterInterfaceEntry(
394+
entry.multicast_router_interface_entry_key);
395+
if (old_entry_ptr == nullptr) {
396+
statuses[i] = ReturnCode(StatusCode::SWSS_RC_INTERNAL)
397+
<< "Multicast router interface entry is missing "
398+
<< QuotedVar(entry.multicast_router_interface_entry_key);
399+
break;
400+
}
401+
402+
// No change to src mac means there is nothing to do.
403+
if (old_entry_ptr->src_mac == entry.src_mac) {
404+
SWSS_LOG_INFO(
405+
"No update required for %s because the src mac did not change",
406+
QuotedVar(entry.multicast_router_interface_entry_key).c_str());
407+
statuses[i] = ReturnCode();
408+
continue;
409+
}
410+
411+
// Confirm RIF OID was assigned (for the old entry).
412+
sai_object_id_t old_rif_oid = getRifOid(old_entry_ptr);
413+
std::string old_rif_key =
414+
KeyGenerator::generateMulticastRouterInterfaceRifKey(
415+
old_entry_ptr->multicast_replica_port, old_entry_ptr->src_mac);
416+
if (old_rif_oid == SAI_NULL_OBJECT_ID) {
417+
statuses[i] =
418+
ReturnCode(StatusCode::SWSS_RC_INTERNAL)
419+
<< "Multicast router interface entry is missing a RIF oid "
420+
<< QuotedVar(old_entry_ptr->multicast_router_interface_entry_key);
421+
break;
422+
}
423+
424+
// Fetch the vector P4MulticastRouterInterfaceEntry associated with the RIF.
425+
if (m_rifOidToRouterInterfaceEntries.find(old_rif_oid) ==
426+
m_rifOidToRouterInterfaceEntries.end()) {
427+
statuses[i] =
428+
ReturnCode(StatusCode::SWSS_RC_INTERNAL)
429+
<< "RIF oid " << old_rif_oid << " missing from map for "
430+
<< QuotedVar(old_entry_ptr->multicast_router_interface_entry_key);
431+
break;
432+
}
433+
auto& old_entries_for_rif = m_rifOidToRouterInterfaceEntries[old_rif_oid];
434+
auto old_entry_with_rif = std::find_if(
435+
old_entries_for_rif.begin(), old_entries_for_rif.end(),
436+
[&](const P4MulticastRouterInterfaceEntry& x) {
437+
return x.multicast_router_interface_entry_key ==
438+
old_entry_ptr->multicast_router_interface_entry_key;
439+
});
440+
if ((old_entry_with_rif == old_entries_for_rif.end()) ||
441+
(m_multicastRouterInterfaceTable.find(
442+
old_entry_ptr->multicast_router_interface_entry_key) ==
443+
m_multicastRouterInterfaceTable.end())) {
444+
statuses[i] =
445+
ReturnCode(StatusCode::SWSS_RC_INTERNAL)
446+
<< "Unable to find entry "
447+
<< QuotedVar(old_entry_ptr->multicast_router_interface_entry_key)
448+
<< " in map";
449+
break;
450+
}
451+
452+
// If we will delete the RIF, confirm there are no more multicast group
453+
// members using it.
454+
if (old_entries_for_rif.size() == 1) {
455+
if (m_rifOidToMulticastGroupMembers.find(old_rif_oid) !=
456+
m_rifOidToMulticastGroupMembers.end()) {
457+
if (m_rifOidToMulticastGroupMembers[old_rif_oid].size() > 0) {
458+
statuses[i] = ReturnCode(StatusCode::SWSS_RC_IN_USE)
459+
<< "RIF oid " << old_rif_oid << " cannot be deleted, "
460+
<< "because it is still used by multicast group "
461+
<< "members";
462+
break;
463+
}
464+
}
465+
}
466+
467+
// Check if new RIF already exists.
468+
// If it doesn't exist, we will have to create one.
469+
bool created_new_rif = false;
470+
std::string rif_key = KeyGenerator::generateMulticastRouterInterfaceRifKey(
471+
entry.multicast_replica_port, entry.src_mac);
472+
473+
sai_object_id_t new_rif_oid = getRifOid(&entry);
474+
// We create a new RIF instead of updating an existing RIF's src mac
475+
// attribute, in case multiple router interface entry tables references
476+
// the same RIF.
477+
if (new_rif_oid == SAI_NULL_OBJECT_ID) {
478+
ReturnCode create_status =
479+
createRouterInterface(rif_key, entry, &new_rif_oid);
480+
statuses[i] = create_status;
481+
if (!create_status.ok()) {
482+
break;
483+
}
484+
created_new_rif = true;
485+
// Internal book-keeping is done after all SAI calls have been performed.
486+
}
487+
488+
// If this entry was the last one associated with the old RIF, we can
489+
// remove that interface.
490+
if (old_entries_for_rif.size() == 1) {
491+
ReturnCode delete_status =
492+
deleteRouterInterface(old_rif_key, old_rif_oid);
493+
statuses[i] = delete_status;
494+
if (!delete_status.ok()) {
495+
break;
496+
}
497+
498+
m_p4OidMapper->eraseOID(SAI_OBJECT_TYPE_ROUTER_INTERFACE, old_rif_key);
499+
gPortsOrch->decreasePortRefCount(old_entry_ptr->multicast_replica_port);
500+
501+
// Since old RIF no longer in use, delete from maps.
502+
old_entries_for_rif.erase(old_entry_with_rif);
503+
m_rifOidToRouterInterfaceEntries.erase(old_rif_oid);
504+
m_rifOidToMulticastGroupMembers.erase(old_rif_oid);
505+
m_rifOids.erase(old_rif_key);
506+
} else {
507+
old_entries_for_rif.erase(old_entry_with_rif);
508+
}
509+
510+
// Always done book keeping.
511+
entry.router_interface_oid = new_rif_oid;
512+
m_multicastRouterInterfaceTable.erase(
513+
old_entry_ptr->multicast_router_interface_entry_key);
514+
// We removed the old P4MulticastRouterInterfaceEntry from the RIF to
515+
// entries vector in the block above.
516+
m_multicastRouterInterfaceTable[entry
517+
.multicast_router_interface_entry_key] =
518+
entry;
519+
m_rifOidToRouterInterfaceEntries[new_rif_oid].push_back(entry);
520+
m_rifOidToMulticastGroupMembers[new_rif_oid] = {};
521+
522+
// Do RIF creation internal accounting at the end to avoid having to back
523+
// out on delete failure.
524+
if (created_new_rif) {
525+
gPortsOrch->increasePortRefCount(entry.multicast_replica_port);
526+
m_p4OidMapper->setOID(SAI_OBJECT_TYPE_ROUTER_INTERFACE, rif_key,
527+
new_rif_oid);
528+
m_rifOids[rif_key] = new_rif_oid;
529+
}
530+
statuses[i] = ReturnCode();
531+
} // for entries
532+
return statuses;
373533
}
374534

375535
std::vector<ReturnCode>
376536
L3MulticastManager::deleteMulticastRouterInterfaceEntries(
377537
const std::vector<P4MulticastRouterInterfaceEntry>& entries) {
378-
std::vector<ReturnCode> rv;
379-
rv.push_back(ReturnCode(StatusCode::SWSS_RC_UNIMPLEMENTED)
380-
<< "L3MulticastManager::deleteMulticastRouterInterfaceEntries "
381-
<< "is not implemented");
382-
return rv;
538+
SWSS_LOG_ENTER();
539+
std::vector<ReturnCode> statuses(entries.size());
540+
fillStatusArrayWithNotExecuted(statuses, 0);
541+
542+
// There are two cases for removal:
543+
// 1. This entry is the last one associated with the RIF. In such a case,
544+
// delete the RIF and clear it from appropriate maps.
545+
// 2. There will still be other entries associated with the RIF. In such a
546+
// case, only remove the current entry from being associated with the RIF.
547+
for (size_t i = 0; i < entries.size(); ++i) {
548+
auto& entry = entries[i];
549+
if (m_multicastRouterInterfaceTable.find(
550+
entry.multicast_router_interface_entry_key) ==
551+
m_multicastRouterInterfaceTable.end()) {
552+
statuses[i] = ReturnCode(StatusCode::SWSS_RC_UNKNOWN)
553+
<< "Multicast router interface entry is not known "
554+
<< QuotedVar(entry.multicast_router_interface_entry_key);
555+
break;
556+
}
557+
558+
// Confirm RIF OID was assigned.
559+
sai_object_id_t rif_oid = getRifOid(&entry);
560+
if (rif_oid == SAI_NULL_OBJECT_ID) {
561+
statuses[i] = ReturnCode(StatusCode::SWSS_RC_INTERNAL)
562+
<< "Multicast router interface entry is missing a RIF oid "
563+
<< QuotedVar(entry.multicast_router_interface_entry_key);
564+
break;
565+
}
566+
567+
// Confirm there are no more multicast group members using the RIF.
568+
if (m_rifOidToMulticastGroupMembers.find(rif_oid) !=
569+
m_rifOidToMulticastGroupMembers.end()) {
570+
if (m_rifOidToMulticastGroupMembers[rif_oid].size() > 0) {
571+
statuses[i] = ReturnCode(StatusCode::SWSS_RC_IN_USE)
572+
<< "RIF oid " << rif_oid << " cannot be deleted, because "
573+
<< "it is still used by multicast group members.";
574+
break;
575+
}
576+
}
577+
578+
// Confirm there is at least one P4MulticastRouterInterfaceEntry associated
579+
// with the RIF.
580+
if (m_rifOidToRouterInterfaceEntries.find(rif_oid) ==
581+
m_rifOidToRouterInterfaceEntries.end()) {
582+
statuses[i] = ReturnCode(StatusCode::SWSS_RC_INTERNAL)
583+
<< "RIF oid " << rif_oid << " missing from map for "
584+
<< QuotedVar(entry.multicast_router_interface_entry_key);
585+
break;
586+
}
587+
auto& entries_for_rif = m_rifOidToRouterInterfaceEntries[rif_oid];
588+
auto entry_with_rif =
589+
std::find_if(entries_for_rif.begin(), entries_for_rif.end(),
590+
[&](const P4MulticastRouterInterfaceEntry& x) {
591+
return x.multicast_router_interface_entry_key ==
592+
entry.multicast_router_interface_entry_key;
593+
});
594+
if ((entry_with_rif == entries_for_rif.end()) ||
595+
(m_multicastRouterInterfaceTable.find(
596+
entry.multicast_router_interface_entry_key) ==
597+
m_multicastRouterInterfaceTable.end())) {
598+
statuses[i] = ReturnCode(StatusCode::SWSS_RC_INTERNAL)
599+
<< "Unable to find entry "
600+
<< QuotedVar(entry.multicast_router_interface_entry_key)
601+
<< " in map";
602+
break;
603+
}
604+
std::string rif_key = KeyGenerator::generateMulticastRouterInterfaceRifKey(
605+
entry.multicast_replica_port, entry.src_mac);
606+
607+
// If this is the last entry, delete the RIF.
608+
// Attempt to delete RIF at SAI layer before adjusting internal maps, in
609+
// case there is an error.
610+
if (entries_for_rif.size() == 1) {
611+
ReturnCode delete_status = deleteRouterInterface(rif_key, rif_oid);
612+
statuses[i] = delete_status;
613+
if (!delete_status.ok()) {
614+
break;
615+
}
616+
617+
m_p4OidMapper->eraseOID(SAI_OBJECT_TYPE_ROUTER_INTERFACE, rif_key);
618+
gPortsOrch->decreasePortRefCount(entry.multicast_replica_port);
619+
620+
// Delete entry from list.
621+
entries_for_rif.erase(entry_with_rif);
622+
// Since RIF no longer in use, delete from maps.
623+
m_rifOidToRouterInterfaceEntries.erase(rif_oid);
624+
m_rifOidToMulticastGroupMembers.erase(rif_oid);
625+
m_rifOids.erase(rif_key);
626+
} else {
627+
// Delete entry from list.
628+
entries_for_rif.erase(entry_with_rif);
629+
}
630+
631+
// Finally, remove the entry P4MulticastRouterInterfaceEntry.
632+
m_multicastRouterInterfaceTable.erase(
633+
entry.multicast_router_interface_entry_key);
634+
statuses[i] = ReturnCode();
635+
} // for i
636+
return statuses;
383637
}
384638

385639
std::vector<ReturnCode> L3MulticastManager::addMulticastReplicationEntries(

0 commit comments

Comments
 (0)