@@ -39,6 +39,13 @@ namespace p4orch {
3939
4040namespace {
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.
4350ReturnCodeOr<std::vector<sai_attribute_t >> prepareRifSaiAttrs (
4451 const P4MulticastRouterInterfaceEntry& multicast_router_interface_entry) {
@@ -288,8 +295,22 @@ ReturnCode L3MulticastManager::createRouterInterface(
288295
289296ReturnCode 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
295316ReturnCode 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(
365384std::vector<ReturnCode>
366385L3MulticastManager::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
375535std::vector<ReturnCode>
376536L3MulticastManager::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
385639std::vector<ReturnCode> L3MulticastManager::addMulticastReplicationEntries (
0 commit comments