Decompose RPC implementation classes
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / rpc / RpcContextImpl.java
index 8f42fab389ac293c5fd98c4c5a186309df987e9d..face6e96160c3a58b32f58273572dc4675409639 100644 (file)
@@ -7,13 +7,10 @@
  */
 package org.opendaylight.openflowplugin.impl.rpc;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterators;
+import com.google.common.collect.ImmutableClassToInstanceMap;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import java.util.Set;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicLong;
 import org.eclipse.jdt.annotation.NonNull;
@@ -29,60 +26,114 @@ import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
 import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
-import org.opendaylight.openflowplugin.impl.services.sal.FlowCapableTransactionServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.NodeConfigServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.PacketProcessingServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalAsyncConfigServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalBundleServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalEchoServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalExperimenterMessageServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalExperimenterMpMessageServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalFlatBatchServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalFlowServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalFlowsBatchServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalGroupServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalGroupsBatchServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalMeterServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalMetersBatchServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalPortServiceImpl;
-import org.opendaylight.openflowplugin.impl.services.sal.SalTableServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightFlowStatisticsServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightFlowTableStatisticsServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightGroupStatisticsServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightMeterStatisticsServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightPortStatisticsServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.OpendaylightQueueStatisticsServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.OpendaylightFlowStatisticsServiceDelegateImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.OpendaylightDirectStatisticsServiceImpl;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer.MultiLayerDirectStatisticsProviderInitializer;
-import org.opendaylight.openflowplugin.impl.statistics.services.direct.singlelayer.SingleLayerDirectStatisticsProviderInitializer;
+import org.opendaylight.openflowplugin.impl.services.SendEchoImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.AddBundleMessagesImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.AddFlowImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.AddFlowsBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.AddGroupImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.AddGroupsBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.AddMeterImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.AddMetersBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.ControlBundleImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.ProcessFlatBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.RemoveFlowImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.RemoveFlowsBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.RemoveGroupImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.RemoveGroupsBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.RemoveMeterImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.RemoveMetersBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SendBarrierImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SendExperimenterImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SendExperimenterMpRequestImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SetConfigImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.TransmitPacketImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.UpdateFlowImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.UpdateFlowsBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.UpdateGroupImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.UpdateGroupsBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.UpdateMeterImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.UpdateMetersBatchImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.UpdatePortImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.UpdateTableImpl;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.GetAsyncImpl;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SetAsyncImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetAggregateFlowStatisticsFromFlowTableForGivenMatchImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetAllGroupStatisticsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetAllMeterConfigStatisticsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetAllMeterStatisticsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetAllNodeConnectorsStatisticsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetAllQueuesStatisticsFromAllPortsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetAllQueuesStatisticsFromGivenPortImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetFlowTablesStatisticsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetGroupDescriptionImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetGroupFeaturesImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetGroupStatisticsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetMeterFeaturesImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetMeterStatisticsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetNodeConnectorStatisticsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.GetQueueStatisticsFromGivenPortImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.GetAggregateFlowStatisticsFromFlowTableForAllFlowsImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.GetAllFlowStatisticsFromFlowTableImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.GetAllFlowsStatisticsFromAllFlowTablesImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.compatibility.GetFlowStatisticsFromFlowTableImpl;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer.MultiGetFlowStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer.MultiGetGroupStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer.MultiGetMeterStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer.MultiGetNodeConnectorStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer.MultiGetQueueStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.singlelayer.SingleGetFlowStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.singlelayer.SingleGetGroupStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.singlelayer.SingleGetMeterStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.singlelayer.SingleGetNodeConnectorStatistics;
+import org.opendaylight.openflowplugin.impl.statistics.services.direct.singlelayer.SingleGetQueueStatistics;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.SalAsyncConfigService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SalEchoService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SalExperimenterMessageService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SalExperimenterMpMessageService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsync;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.SetAsync;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SendEcho;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SendExperimenter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescription;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.NodeConfigService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.SalBundleService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.SalPortService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
-import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.SetConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessages;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundle;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromGivenPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetQueueStatisticsFromGivenPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTable;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.Rpc;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -93,10 +144,6 @@ final class RpcContextImpl implements RpcContext {
     private final MessageSpy messageSpy;
     private final Semaphore tracker;
     private final boolean isStatisticsRpcEnabled;
-
-    // TODO: add private Sal salBroker
-    private final ConcurrentMap<Class<?>, ObjectRegistration<? extends RpcService>> rpcRegistrations =
-            new ConcurrentHashMap<>();
     private final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
     private final DeviceInfo deviceInfo;
     private final DeviceContext deviceContext;
@@ -105,6 +152,7 @@ final class RpcContextImpl implements RpcContext {
     private final NotificationPublishService notificationPublishService;
 
     private ContextChainMastershipWatcher contextChainMastershipWatcher = null;
+    private Registration rpcRegistration;
 
     RpcContextImpl(@NonNull final RpcProviderService rpcProviderRegistry,
                    final int maxRequests,
@@ -125,18 +173,9 @@ final class RpcContextImpl implements RpcContext {
         tracker = new Semaphore(maxRequests, true);
     }
 
-    private <S extends RpcService> void registerRpcServiceImplementation(final Class<S> serviceClass,
-            final S serviceInstance) {
-        if (!rpcRegistrations.containsKey(serviceClass)) {
-            final ObjectRegistration<S> routedRpcReg = rpcProviderRegistry.registerRpcImplementation(serviceClass,
-                serviceInstance, ImmutableSet.of(nodeInstanceIdentifier));
-            rpcRegistrations.put(serviceClass, routedRpcReg);
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Registration of service {} for device {}.",
-                        serviceClass.getSimpleName(),
-                        nodeInstanceIdentifier.getKey().getId().getValue());
-            }
-        }
+    @Override
+    public ServiceGroupIdentifier getIdentifier() {
+        return deviceInfo.getServiceIdentifier();
     }
 
     @Override
@@ -145,15 +184,10 @@ final class RpcContextImpl implements RpcContext {
     }
 
     private void unregisterRPCs() {
-        for (var iterator = Iterators.consumingIterator(rpcRegistrations.entrySet().iterator()); iterator.hasNext(); ) {
-            final var rpcRegistration = iterator.next().getValue();
+        if (rpcRegistration != null) {
+            LOG.debug("Closing RPC registrations for device {}.", nodeInstanceIdentifier.getKey().getId().getValue());
             rpcRegistration.close();
-
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Closing RPC Registration of service {} for device {}.",
-                        rpcRegistration.getInstance().getClass().getSimpleName(),
-                        nodeInstanceIdentifier.getKey().getId().getValue());
-            }
+            rpcRegistration = null;
         }
     }
 
@@ -185,11 +219,6 @@ final class RpcContextImpl implements RpcContext {
         };
     }
 
-    @VisibleForTesting
-    boolean isEmptyRpcRegistrations() {
-        return rpcRegistrations.isEmpty();
-    }
-
     @Override
     public DeviceInfo getDeviceInfo() {
         return deviceInfo;
@@ -208,94 +237,176 @@ final class RpcContextImpl implements RpcContext {
 
     @Override
     public void instantiateServiceInstance() {
-        // TODO: Use multipart writer provider from device context
-        final var multipartWriterProvider = MultipartWriterProviderFactory.createDefaultProvider(deviceContext);
+        // flow-capable-transaction.yang
+        final var sendBarrier = new SendBarrierImpl(this, deviceContext);
+
+        // sal-experimenter-message.yang
+        final var sendExperimenter = new SendExperimenterImpl(this, deviceContext, extensionConverterProvider);
 
-        // create service instances
-        final var salFlowService = new SalFlowServiceImpl(this, deviceContext, convertorExecutor);
-        final var flowCapableTransactionService = new FlowCapableTransactionServiceImpl(this, deviceContext);
-        final var salAsyncConfigService = new SalAsyncConfigServiceImpl(this, deviceContext);
-        final var salGroupService = new SalGroupServiceImpl(this, deviceContext, convertorExecutor);
-        final var salMeterService = new SalMeterServiceImpl(this, deviceContext, convertorExecutor);
-        final var flowStatisticsService = OpendaylightFlowStatisticsServiceImpl.createWithOook(this, deviceContext,
-            convertorExecutor);
+        // sal-flow.yang
+        final var addFlow = new AddFlowImpl(this, deviceContext, convertorExecutor);
+        final var removeFlow = new RemoveFlowImpl(this, deviceContext, convertorExecutor);
+        final var updateFlow = new UpdateFlowImpl(this, deviceContext, convertorExecutor);
 
-        // register routed service instances
-        registerRpcServiceImplementation(SalEchoService.class, new SalEchoServiceImpl(this, deviceContext));
-        registerRpcServiceImplementation(SalFlowService.class, salFlowService);
-        registerRpcServiceImplementation(FlowCapableTransactionService.class, flowCapableTransactionService);
-        registerRpcServiceImplementation(SalAsyncConfigService.class, salAsyncConfigService);
-        registerRpcServiceImplementation(SalMeterService.class, salMeterService);
-        registerRpcServiceImplementation(SalGroupService.class, salGroupService);
-        registerRpcServiceImplementation(SalTableService.class,
-            new SalTableServiceImpl(this, deviceContext, convertorExecutor, multipartWriterProvider));
-        registerRpcServiceImplementation(SalPortService.class,
-            new SalPortServiceImpl(this, deviceContext, convertorExecutor));
-        registerRpcServiceImplementation(PacketProcessingService.class,
-            new PacketProcessingServiceImpl(this, deviceContext, convertorExecutor));
-        registerRpcServiceImplementation(NodeConfigService.class, new NodeConfigServiceImpl(this, deviceContext));
-        registerRpcServiceImplementation(OpendaylightFlowStatisticsService.class, flowStatisticsService);
+        // sal-group.yang
+        final var addGroup = new AddGroupImpl(this, deviceContext, convertorExecutor);
+        final var removeGroup = new RemoveGroupImpl(this, deviceContext, convertorExecutor);
+        final var updateGroup = new UpdateGroupImpl(this, deviceContext, convertorExecutor);
 
-        // register direct statistics gathering services
-        registerRpcServiceImplementation(OpendaylightDirectStatisticsService.class,
-            new OpendaylightDirectStatisticsServiceImpl(deviceContext.canUseSingleLayerSerialization()
-                ? SingleLayerDirectStatisticsProviderInitializer.createProvider(this, deviceContext, convertorExecutor,
-                    multipartWriterProvider)
-                : MultiLayerDirectStatisticsProviderInitializer.createProvider(this, deviceContext, convertorExecutor,
-                    multipartWriterProvider)));
+        // sal-meter.yang
+        final var addMeter = new AddMeterImpl(this, deviceContext, convertorExecutor);
+        final var removeMeter = new RemoveMeterImpl(this, deviceContext, convertorExecutor);
+        final var updateMeter = new UpdateMeterImpl(this, deviceContext, convertorExecutor);
 
-        // register flat batch services
-        registerRpcServiceImplementation(SalFlatBatchService.class, new SalFlatBatchServiceImpl(
-            new SalFlowsBatchServiceImpl(salFlowService, flowCapableTransactionService),
-            new SalGroupsBatchServiceImpl(salGroupService, flowCapableTransactionService),
-            new SalMetersBatchServiceImpl(salMeterService, flowCapableTransactionService)));
+        // FIXME: Use multipart writer provider from device context
+        final var multipartWriterProvider = MultipartWriterProviderFactory.createDefaultProvider(deviceContext);
 
-        // register experimenter services
-        registerRpcServiceImplementation(SalExperimenterMessageService.class,
-            new SalExperimenterMessageServiceImpl(this, deviceContext, extensionConverterProvider));
-        registerRpcServiceImplementation(SalExperimenterMpMessageService.class,
-            new SalExperimenterMpMessageServiceImpl(this, deviceContext, extensionConverterProvider));
+        final var singleLayer = deviceContext.canUseSingleLayerSerialization();
 
-        //register onf extension bundles
-        registerRpcServiceImplementation(SalBundleService.class, new SalBundleServiceImpl(
-            new SalExperimenterMessageServiceImpl(this, deviceContext, extensionConverterProvider)));
+        final var builder = ImmutableClassToInstanceMap.<Rpc<?, ?>>builder()
+            .put(SendBarrier.class, sendBarrier)
+            // node-config.yang
+            .put(SetConfig.class, new SetConfigImpl(this, deviceContext))
+            // packet-processing.yang
+            .put(TransmitPacket.class, new TransmitPacketImpl(this, deviceContext, convertorExecutor))
+            // sal-async-config.yang
+            .put(GetAsync.class, new GetAsyncImpl(this, deviceContext))
+            .put(SetAsync.class, new SetAsyncImpl(this, deviceContext))
+            // sal-echo.yang
+            .put(SendEcho.class, new SendEchoImpl(this, deviceContext))
+            .put(SendExperimenter.class, sendExperimenter)
+            // sal-bundle.yang (ONF extension?)
+            .put(ControlBundle.class, new ControlBundleImpl(sendExperimenter))
+            .put(AddBundleMessages.class, new AddBundleMessagesImpl(sendExperimenter))
+            // sal-experimenter-mp-message.yang
+            .put(SendExperimenterMpRequest.class, new SendExperimenterMpRequestImpl(this, deviceContext,
+                extensionConverterProvider))
+            .put(AddFlow.class, addFlow)
+            .put(RemoveFlow.class, removeFlow)
+            .put(UpdateFlow.class, updateFlow)
+            .put(AddGroup.class, addGroup)
+            .put(RemoveGroup.class, removeGroup)
+            .put(UpdateGroup.class, updateGroup)
+            .put(AddMeter.class, addMeter)
+            .put(RemoveMeter.class, removeMeter)
+            .put(UpdateMeter.class, updateMeter)
+            // sal-port.yang
+            .put(UpdatePort.class, new UpdatePortImpl(this, deviceContext, convertorExecutor))
+            // sal-flat-batch.yang
+            .put(ProcessFlatBatch.class, new ProcessFlatBatchImpl(
+                // sal-flows-batch.yang
+                // FIXME: register these?
+                new AddFlowsBatchImpl(addFlow, sendBarrier),
+                new RemoveFlowsBatchImpl(removeFlow, sendBarrier),
+                new UpdateFlowsBatchImpl(updateFlow, sendBarrier),
+                // sal-groups-batch.yang
+                // FIXME: register these?
+                new AddGroupsBatchImpl(addGroup, sendBarrier),
+                new RemoveGroupsBatchImpl(removeGroup, sendBarrier),
+                new UpdateGroupsBatchImpl(updateGroup, sendBarrier),
+                // sal-meters-batch.yang
+                // FIXME: register these?
+                new AddMetersBatchImpl(addMeter, sendBarrier),
+                new RemoveMetersBatchImpl(removeMeter, sendBarrier),
+                new UpdateMetersBatchImpl(updateMeter, sendBarrier)))
+            // sal-table.yang
+            .put(UpdateTable.class, new UpdateTableImpl(this, deviceContext, convertorExecutor,
+                multipartWriterProvider))
+            // opendaylight-flow-statistics.yang
+            .put(GetAggregateFlowStatisticsFromFlowTableForGivenMatch.class,
+                new GetAggregateFlowStatisticsFromFlowTableForGivenMatchImpl(this, deviceContext, convertorExecutor))
+            // opendaylight-direct-statistics.yang
+            .put(GetFlowStatistics.class, singleLayer
+                ? new SingleGetFlowStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider)
+                : new MultiGetFlowStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider))
+            .put(GetGroupStatistics.class, singleLayer
+                ? new SingleGetGroupStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider)
+                : new MultiGetGroupStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider))
+            .put(GetQueueStatistics.class, singleLayer
+                ? new SingleGetQueueStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider)
+                : new MultiGetQueueStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider))
+            .put(GetMeterStatistics.class, singleLayer
+                ? new SingleGetMeterStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider)
+                : new MultiGetMeterStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider))
+            .put(GetNodeConnectorStatistics.class, singleLayer
+                ? new SingleGetNodeConnectorStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider)
+                : new MultiGetNodeConnectorStatistics(this, deviceContext, convertorExecutor, multipartWriterProvider));
 
         // Support deprecated statistic related services for backward compatibility. The only exception from deprecation
         // is the aggregated flow statistic with match criteria input.
         if (isStatisticsRpcEnabled && !deviceContext.canUseSingleLayerSerialization()) {
             final var compatibilityXidSeed = new AtomicLong();
+            // FIXME: why is this separate?
+            final var statsCompatXidSeed = new AtomicLong();
 
-            // attach delegate to flow statistics service (to cover all but aggregated stats with match filter input)
-            final var flowStatisticsDelegate = new OpendaylightFlowStatisticsServiceDelegateImpl(this, deviceContext,
-                notificationPublishService, new AtomicLong(), convertorExecutor);
-            flowStatisticsService.setDelegate(flowStatisticsDelegate);
+            builder
+                // Legacy RPCs
+                .put(GetAggregateFlowStatisticsFromFlowTableForAllFlows.class,
+                    new GetAggregateFlowStatisticsFromFlowTableForAllFlowsImpl(this, deviceContext, convertorExecutor,
+                        statsCompatXidSeed, notificationPublishService))
+                .put(GetAllFlowStatisticsFromFlowTable.class,
+                    new GetAllFlowStatisticsFromFlowTableImpl(this, deviceContext, convertorExecutor,
+                        statsCompatXidSeed, notificationPublishService))
+                .put(GetAllFlowsStatisticsFromAllFlowTables.class,
+                    new GetAllFlowsStatisticsFromAllFlowTablesImpl(this, deviceContext, convertorExecutor,
+                        statsCompatXidSeed, notificationPublishService))
+                .put(GetFlowStatisticsFromFlowTable.class,
+                    new GetFlowStatisticsFromFlowTableImpl(this, deviceContext, convertorExecutor, statsCompatXidSeed,
+                        notificationPublishService))
 
-            // register all statistics (deprecated) services
-            registerRpcServiceImplementation(OpendaylightFlowTableStatisticsService.class,
-                new OpendaylightFlowTableStatisticsServiceImpl(this, deviceContext,
-                    compatibilityXidSeed, notificationPublishService));
-            registerRpcServiceImplementation(OpendaylightGroupStatisticsService.class,
-                new OpendaylightGroupStatisticsServiceImpl(this, deviceContext,
-                    compatibilityXidSeed, notificationPublishService, convertorExecutor));
-            registerRpcServiceImplementation(OpendaylightMeterStatisticsService.class,
-                new OpendaylightMeterStatisticsServiceImpl(this, deviceContext,
-                    compatibilityXidSeed, notificationPublishService, convertorExecutor));
-            registerRpcServiceImplementation(OpendaylightQueueStatisticsService.class,
-                new OpendaylightQueueStatisticsServiceImpl(this, deviceContext,
-                    compatibilityXidSeed, notificationPublishService));
-            registerRpcServiceImplementation(OpendaylightPortStatisticsService.class,
-                new OpendaylightPortStatisticsServiceImpl(this, deviceContext,
-                    compatibilityXidSeed, notificationPublishService));
+                // register all statistics (deprecated) services
+                .put(GetFlowTablesStatistics.class,
+                    new GetFlowTablesStatisticsImpl(this, deviceContext, compatibilityXidSeed,
+                        notificationPublishService))
+                .put(org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupStatistics.class,
+                    new GetGroupStatisticsImpl(this, deviceContext, compatibilityXidSeed, notificationPublishService,
+                        convertorExecutor))
+                .put(GetAllGroupStatistics.class,
+                    new GetAllGroupStatisticsImpl(this, deviceContext, compatibilityXidSeed, notificationPublishService,
+                        convertorExecutor))
+                .put(GetGroupDescription.class,
+                    new GetGroupDescriptionImpl(this, deviceContext, compatibilityXidSeed, notificationPublishService,
+                        convertorExecutor))
+                .put(GetGroupFeatures.class,
+                    new GetGroupFeaturesImpl(this, deviceContext, compatibilityXidSeed, notificationPublishService,
+                        convertorExecutor))
+                .put(org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterStatistics.class,
+                    new GetMeterStatisticsImpl(this, deviceContext, compatibilityXidSeed, notificationPublishService,
+                        convertorExecutor))
+                .put(org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111
+                        .GetAllMeterStatistics.class,
+                    new GetAllMeterStatisticsImpl(this, deviceContext, compatibilityXidSeed, notificationPublishService,
+                        convertorExecutor))
+                .put(GetAllMeterConfigStatistics.class,
+                    new GetAllMeterConfigStatisticsImpl(this, deviceContext, compatibilityXidSeed,
+                        notificationPublishService, convertorExecutor))
+                .put(GetMeterFeatures.class,
+                    new GetMeterFeaturesImpl(this, deviceContext, compatibilityXidSeed, notificationPublishService,
+                        convertorExecutor))
+                .put(GetQueueStatisticsFromGivenPort.class,
+                    new GetQueueStatisticsFromGivenPortImpl(this, deviceContext, compatibilityXidSeed,
+                        notificationPublishService))
+                .put(GetAllQueuesStatisticsFromAllPorts.class,
+                    new GetAllQueuesStatisticsFromAllPortsImpl(this, deviceContext, compatibilityXidSeed,
+                        notificationPublishService))
+                .put(GetAllQueuesStatisticsFromGivenPort.class,
+                    new GetAllQueuesStatisticsFromGivenPortImpl(this, deviceContext, compatibilityXidSeed,
+                        notificationPublishService))
+                .put(org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214
+                    .GetNodeConnectorStatistics.class,
+                    new GetNodeConnectorStatisticsImpl(this, deviceContext, compatibilityXidSeed,
+                        notificationPublishService))
+                .put(GetAllNodeConnectorsStatistics.class,
+                    new GetAllNodeConnectorsStatisticsImpl(this, deviceContext, compatibilityXidSeed,
+                        notificationPublishService));
         }
 
+        rpcRegistration = rpcProviderRegistry.registerRpcImplementations(builder.build(),
+            Set.of(nodeInstanceIdentifier));
+
         final var local = contextChainMastershipWatcher;
         if (local != null) {
             local.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.RPC_REGISTRATION);
         }
     }
-
-    @Override
-    public ServiceGroupIdentifier getIdentifier() {
-        return deviceInfo.getServiceIdentifier();
-    }
 }