@@ -32,6 +32,7 @@ extern sai_object_id_t gSwitchId;
3232extern sai_object_id_t gVirtualRouterId ;
3333extern sai_ipmc_group_api_t * sai_ipmc_group_api;
3434extern sai_router_interface_api_t * sai_router_intfs_api;
35+ extern sai_bridge_api_t * sai_bridge_api;
3536
3637extern PortsOrch* gPortsOrch ;
3738
@@ -820,11 +821,10 @@ ReturnCode L3MulticastManager::validateL3SetMulticastRouterInterfaceEntry(
820821 << " RIF was not assigned before updating multicast router "
821822 " interface "
822823 " entry with keys "
823- << QuotedVar (
824- multicast_router_interface_entry.multicast_replica_port )
824+ << QuotedVar (multicast_router_interface_entry.multicast_replica_port )
825825 << " and "
826- << QuotedVar (multicast_router_interface_entry
827- .multicast_replica_instance );
826+ << QuotedVar (
827+ multicast_router_interface_entry .multicast_replica_instance );
828828 }
829829
830830 // Confirm we have a reference to the RIF object ID.
@@ -876,10 +876,11 @@ ReturnCode L3MulticastManager::validateSetMulticastRouterInterfaceEntry(
876876 router_interface_entry_ptr->action ) {
877877 return ReturnCode (StatusCode::SWSS_RC_INVALID_PARAM)
878878 << " Multicast router interface entry with key "
879- << QuotedVar (multicast_router_interface_entry.multicast_router_interface_entry_key )
879+ << QuotedVar (multicast_router_interface_entry
880+ .multicast_router_interface_entry_key )
880881 << " cannot change action from "
881- << QuotedVar (router_interface_entry_ptr->action )
882- << " to " << QuotedVar (multicast_router_interface_entry.action );
882+ << QuotedVar (router_interface_entry_ptr->action ) << " to "
883+ << QuotedVar (multicast_router_interface_entry.action );
883884 }
884885
885886 if (multicast_router_interface_entry.action == p4orch::kSetMulticastSrcMac ) {
@@ -1009,6 +1010,42 @@ ReturnCode L3MulticastManager::processMulticastGroupEntries(
10091010 return status;
10101011}
10111012
1013+ ReturnCode L3MulticastManager::createBridgePort (
1014+ P4MulticastRouterInterfaceEntry& entry, sai_object_id_t * bridge_port_oid) {
1015+ SWSS_LOG_ENTER ();
1016+
1017+ Port port;
1018+ if (!gPortsOrch ->getPort (entry.multicast_replica_port , port)) {
1019+ LOG_ERROR_AND_RETURN (ReturnCode (StatusCode::SWSS_RC_NOT_FOUND)
1020+ << " Unable to find port object "
1021+ << QuotedVar (entry.multicast_replica_port )
1022+ << " to create bridge port" );
1023+ }
1024+
1025+ std::vector<sai_attribute_t > attrs;
1026+ sai_attribute_t attr;
1027+
1028+ attr.id = SAI_BRIDGE_PORT_ATTR_TYPE;
1029+ attr.value .s32 = SAI_BRIDGE_PORT_TYPE_PORT;
1030+ attrs.push_back (attr);
1031+
1032+ attr.id = SAI_BRIDGE_PORT_ATTR_PORT_ID;
1033+ attr.value .oid = port.m_port_id ;
1034+ attrs.push_back (attr);
1035+
1036+ sai_status_t status = sai_bridge_api->create_bridge_port (
1037+ bridge_port_oid, gSwitchId , (uint32_t )attrs.size (), attrs.data ());
1038+
1039+ if (status != SAI_STATUS_SUCCESS) {
1040+ LOG_ERROR_AND_RETURN (
1041+ ReturnCode (status)
1042+ << " Failed to create bridge port for L2 multicast on port "
1043+ << QuotedVar (entry.multicast_replica_port ));
1044+ }
1045+
1046+ return ReturnCode ();
1047+ }
1048+
10121049ReturnCode L3MulticastManager::createRouterInterface (
10131050 const std::string& rif_key, P4MulticastRouterInterfaceEntry& entry,
10141051 sai_object_id_t * rif_oid) {
@@ -1136,6 +1173,26 @@ ReturnCode L3MulticastManager::deleteMulticastGroup(
11361173
11371174std::vector<ReturnCode> L3MulticastManager::addMulticastRouterInterfaceEntries (
11381175 std::vector<P4MulticastRouterInterfaceEntry>& entries) {
1176+ SWSS_LOG_ENTER ();
1177+ std::vector<ReturnCode> statuses (entries.size ());
1178+ fillStatusArrayWithNotExecuted (statuses, 0 );
1179+
1180+ for (size_t i = 0 ; i < entries.size (); ++i) {
1181+ auto & entry = entries[i];
1182+ if (entry.action == p4orch::kSetMulticastSrcMac ) {
1183+ statuses[i] = addL3MulticastRouterInterfaceEntry (entry);
1184+ } else {
1185+ statuses[i] = addL2MulticastRouterInterfaceEntry (entry);
1186+ }
1187+ if (!statuses[i].ok ()) {
1188+ break ;
1189+ }
1190+ }
1191+ return statuses;
1192+ }
1193+
1194+ ReturnCode L3MulticastManager::addL3MulticastRouterInterfaceEntry (
1195+ P4MulticastRouterInterfaceEntry& entry) {
11391196 // There are two cases for add:
11401197 // 1. The new entry (multicast_replica_port, multicast_replica_instance) will
11411198 // need a new RIF allocated.
@@ -1144,43 +1201,52 @@ std::vector<ReturnCode> L3MulticastManager::addMulticastRouterInterfaceEntries(
11441201 // src mac, and src mac is the action parameter associated with a table entry.
11451202 SWSS_LOG_ENTER ();
11461203
1147- std::vector<ReturnCode> statuses (entries. size () );
1148- fillStatusArrayWithNotExecuted (statuses, 0 );
1149- for ( size_t i = 0 ; i < entries. size (); ++i) {
1150- auto & entry = entries[i] ;
1204+ sai_object_id_t rif_oid = getRifOid (&entry );
1205+ if (rif_oid == SAI_NULL_OBJECT_ID) {
1206+ std::string rif_key = KeyGenerator::generateMulticastRouterInterfaceRifKey (
1207+ entry. multicast_replica_port , entry. src_mac ) ;
11511208
1152- sai_object_id_t rif_oid = getRifOid (&entry);
1153- if (rif_oid == SAI_NULL_OBJECT_ID) {
1154- std::string rif_key =
1155- KeyGenerator::generateMulticastRouterInterfaceRifKey (
1156- entry.multicast_replica_port , entry.src_mac );
1209+ RETURN_IF_ERROR (createRouterInterface (rif_key, entry, &rif_oid));
11571210
1158- ReturnCode create_status =
1159- createRouterInterface (rif_key, entry, &rif_oid);
1160- statuses[i] = create_status;
1161- if (!create_status.ok ()) {
1162- break ;
1163- }
1211+ gPortsOrch ->increasePortRefCount (entry.multicast_replica_port );
1212+ m_p4OidMapper->setOID (SAI_OBJECT_TYPE_ROUTER_INTERFACE, rif_key, rif_oid);
1213+ m_rifOids[rif_key] = rif_oid;
1214+ m_rifOidToMulticastGroupMembers[rif_oid] = {};
1215+ }
11641216
1165- gPortsOrch ->increasePortRefCount (entry.multicast_replica_port );
1166- m_p4OidMapper->setOID (SAI_OBJECT_TYPE_ROUTER_INTERFACE, rif_key, rif_oid);
1167- m_rifOids[rif_key] = rif_oid;
1168- m_rifOidToMulticastGroupMembers[rif_oid] = {};
1169- }
1217+ // Operations done regardless of whether RIF was created or not.
1218+ // Set the entry RIF.
1219+ entry.router_interface_oid = rif_oid;
11701220
1171- // Operations done regardless of whether RIF was created or not.
1172- // Set the entry RIF.
1173- entry.router_interface_oid = rif_oid;
1221+ // Update internal state.
1222+ m_multicastRouterInterfaceTable[entry.multicast_router_interface_entry_key ] =
1223+ entry;
1224+ m_rifOidToRouterInterfaceEntries[rif_oid].push_back (entry);
1225+ return ReturnCode ();
1226+ }
11741227
1175- // Update internal state.
1176- m_multicastRouterInterfaceTable[entry
1177- .multicast_router_interface_entry_key ] =
1178- entry;
1179- m_rifOidToRouterInterfaceEntries[rif_oid].push_back (entry);
1228+ ReturnCode L3MulticastManager::addL2MulticastRouterInterfaceEntry (
1229+ P4MulticastRouterInterfaceEntry& entry) {
1230+ // There are two cases for add:
1231+ // 1. The new entry (multicast_replica_port, multicast_replica_instance) will
1232+ // need a new bridge port allocated.
1233+ // 2. The new entry will be able to use an existing bridge port.
1234+ // Recall that bridge ports depend only on the multicast_replica_port.
1235+ SWSS_LOG_ENTER ();
11801236
1181- statuses[i] = ReturnCode ();
1182- } // for i
1183- return statuses;
1237+ sai_object_id_t bridge_port_oid = getBridgePortOid (&entry);
1238+ if (bridge_port_oid == SAI_NULL_OBJECT_ID) {
1239+ RETURN_IF_ERROR (createBridgePort (entry, &bridge_port_oid));
1240+ gPortsOrch ->increasePortRefCount (entry.multicast_replica_port );
1241+ m_p4OidMapper->setOID (SAI_OBJECT_TYPE_BRIDGE_PORT,
1242+ entry.multicast_replica_port , bridge_port_oid);
1243+ }
1244+
1245+ // Operations done regardless of whether bridge port was created or not.
1246+ // Set the entry bridge port.
1247+ m_multicastRouterInterfaceTable[entry.multicast_router_interface_entry_key ] =
1248+ entry;
1249+ return ReturnCode ();
11841250}
11851251
11861252std::vector<ReturnCode>
@@ -2172,14 +2238,7 @@ std::string L3MulticastManager::verifyMulticastGroupStateCache(
21722238
21732239std::string L3MulticastManager::verifyMulticastGroupStateAsicDb (
21742240 const P4MulticastGroupEntry* multicast_group_entry) {
2175-
21762241 // Confirm group settings.
2177- std::vector<sai_attribute_t > group_attrs; // no required attributes
2178- std::vector<swss::FieldValueTuple> exp =
2179- saimeta::SaiAttributeList::serialize_attr_list (
2180- SAI_OBJECT_TYPE_IPMC_GROUP, (uint32_t )group_attrs.size (),
2181- group_attrs.data (), /* countOnly=*/ false );
2182-
21832242 swss::DBConnector db (" ASIC_DB" , 0 );
21842243 swss::Table table (&db, " ASIC_STATE" );
21852244 std::string key =
@@ -2189,12 +2248,9 @@ std::string L3MulticastManager::verifyMulticastGroupStateAsicDb(
21892248 if (!table.get (key, values)) {
21902249 return std::string (" ASIC DB key not found " ) + key;
21912250 }
2192- std::string group_msg =
2193- verifyAttrs (values, exp, std::vector<swss::FieldValueTuple>{},
2194- /* allow_unknown=*/ false );
2195- if (!group_msg.empty ()) {
2196- return group_msg;
2197- }
2251+ // There are no IPMC group attributes to verify. The attributes that do
2252+ // exist are read-only attributes related to how many group members there are.
2253+ // We check group members and their attributes below.
21982254
21992255 // Confirm group member settings.
22002256 for (auto & replica : multicast_group_entry->replicas ) {
@@ -2217,7 +2273,8 @@ std::string L3MulticastManager::verifyMulticastGroupStateAsicDb(
22172273
22182274 auto member_attrs = prepareMulticastGroupMemberSaiAttrs (
22192275 multicast_group_entry->multicast_group_oid , rif_oid);
2220- exp = saimeta::SaiAttributeList::serialize_attr_list (
2276+ std::vector<swss::FieldValueTuple> exp =
2277+ saimeta::SaiAttributeList::serialize_attr_list (
22212278 SAI_OBJECT_TYPE_IPMC_GROUP_MEMBER, (uint32_t )member_attrs.size (),
22222279 member_attrs.data (), /* countOnly=*/ false );
22232280 key = sai_serialize_object_type (SAI_OBJECT_TYPE_IPMC_GROUP_MEMBER) + " :" +
@@ -2270,6 +2327,17 @@ sai_object_id_t L3MulticastManager::getRifOid(
22702327 return m_rifOids[rif_key];
22712328}
22722329
2330+ // A bridge port is associated with an egress port.
2331+ sai_object_id_t L3MulticastManager::getBridgePortOid (
2332+ const P4MulticastRouterInterfaceEntry* multicast_router_interface_entry) {
2333+ sai_object_id_t bridge_port_oid = SAI_NULL_OBJECT_ID;
2334+ m_p4OidMapper->getOID (
2335+ SAI_OBJECT_TYPE_BRIDGE_PORT,
2336+ multicast_router_interface_entry->multicast_replica_port ,
2337+ &bridge_port_oid);
2338+ return bridge_port_oid;
2339+ }
2340+
22732341// A RIF is associated with an egress port and Ethernet src mac value.
22742342sai_object_id_t L3MulticastManager::getRifOid (const P4Replica& replica) {
22752343
0 commit comments