Updates to support new TrafficProfiles that require a user-specified Direction in...
[packetcable.git] / packetcable-policy-server / src / main / java / org / opendaylight / controller / packetcable / provider / PacketcableProvider.java
index 1bbf5b283d63eb75887f53cac290d61413a5c4d3..b155759b9a1a26ded212461d350659fef958ed59 100644 (file)
@@ -52,44 +52,48 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.AppContext;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapContext;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapPollConnectionInput;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapPollConnectionOutput;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapPollConnectionOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapSetConnectionInput;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapSetConnectionOutput;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.CcapSetConnectionOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.Ccaps;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.PacketcableService;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.Qos;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.QosPollGatesInput;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.QosPollGatesOutput;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.QosPollGatesOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ServiceClassName;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ServiceFlowDirection;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.attributes.ConnectionBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccaps.Ccap;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccaps.CcapBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.Apps;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.App;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.AppBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.AppKey;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.Subscribers;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.SubscribersBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.Subscriber;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.SubscriberBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.SubscriberKey;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.Gates;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.GatesBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.Gate;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.GateBuilder;
-import org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.GateKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.AppContext;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.CcapContext;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.CcapPollConnectionInput;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.CcapPollConnectionOutput;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.CcapPollConnectionOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.CcapSetConnectionInput;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.CcapSetConnectionOutput;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.CcapSetConnectionOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.PacketcableService;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.Qos;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.QosPollGatesInput;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.QosPollGatesOutput;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.QosPollGatesOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ServiceClassName;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ServiceFlowDirection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.attributes.ConnectionBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccaps.Ccap;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccaps.CcapBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gate.spec.GateSpec;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gate.spec.GateSpecBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.Apps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.App;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.AppBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.AppKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.Subscribers;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.SubscribersBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.subscribers.Subscriber;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.subscribers.SubscriberBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.subscribers.SubscriberKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.subscribers.subscriber.Gates;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.subscribers.subscriber.GatesBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.Gate;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.GateBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.GateKey;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.pcmm.gates.impl.DOCSISServiceClassNameTrafficProfile;
+import org.pcmm.gates.IGateSpec.Direction;
 import org.pcmm.rcd.IPCMMClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -151,8 +155,7 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
     @Override
     public void onSessionInitiated(ProviderContext session) {
         logger.info("Packetcable Session Initiated");
-        logger.info("logging levels: error={}, warn={}, info={}, debug={}, trace={}", logger.isErrorEnabled(),
-                logger.isWarnEnabled(), logger.isInfoEnabled(), logger.isDebugEnabled(), logger.isTraceEnabled());
+        logger.info("logging levels: error={}, warn={}, info={}, debug={}, trace={}", logger.isErrorEnabled(), logger.isWarnEnabled(), logger.isInfoEnabled(), logger.isDebugEnabled(), logger.isTraceEnabled());
 
         dataBroker = session.getSALService(DataBroker.class);
 
@@ -303,7 +306,7 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
     // ValidationException does not need to be thrown again
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     private <T extends DataObject> void saveErrors(@Nonnull Map<InstanceIdentifier<T>, ValidationException> errorMap,
-            @Nonnull Map<InstanceIdentifier<T>, T> dataMap) {
+                                                   @Nonnull Map<InstanceIdentifier<T>, T> dataMap) {
 
         final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
 
@@ -611,7 +614,7 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
 
         @Override
         protected void handleUpdatedData(final Map<InstanceIdentifier<Ccap>, Ccap> updatedCcaps,
-                final Map<InstanceIdentifier<Ccap>, Ccap> originalCcaps) {
+                                         final Map<InstanceIdentifier<Ccap>, Ccap> originalCcaps) {
 
             // TODO actually support updates
 
@@ -644,7 +647,7 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
 
         @Override
         protected void handleRemovedData(final Set<InstanceIdentifier<Ccap>> removedCcapPaths,
-                final Map<InstanceIdentifier<Ccap>, Ccap> originalCcaps) {
+                                         final Map<InstanceIdentifier<Ccap>, Ccap> originalCcaps) {
 
             for (InstanceIdentifier<Ccap> iid : removedCcapPaths) {
                 final Ccap nukedCcap = originalCcaps.get(iid);
@@ -733,16 +736,6 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
                     continue;
                 }
 
-                final ServiceClassName scn = newGate.getTrafficProfile().getServiceClassName();
-                final ServiceFlowDirection scnDirection = findScnOnCcap(scn, ccap);
-                if (scnDirection == null) {
-                    final String msg =
-                            String.format("SCN %s not found on CCAP %s for %s", scn, ccap.getCcapId(), newGatePathStr);
-                    logger.error(msg);
-                    saveGateError(gateIID, newGatePathStr, msg);
-                    continue;
-                }
-
                 final PCMMService pcmmService = pcmmServiceMap.get(ccap.getCcapId());
                 if (pcmmService == null) {
                     final String msg =
@@ -753,33 +746,78 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
                     continue;
                 }
 
-                PCMMService.GateSendStatus status =
-                        pcmmService.sendGateSet(newGatePathStr, subscriberAddr, newGate, scnDirection);
-                if (status.didSucceed()) {
-                    gateMap.put(newGatePathStr, newGate);
-                    gateCcapMap.put(newGatePathStr, ccap.getCcapId());
-                }
+                //
+                // set up gate builder with known fields (and some empty ones)
+                //
                 final GateBuilder gateBuilder = new GateBuilder();
                 gateBuilder.setGateId(newGate.getGateId())
                         .setGatePath(newGatePathStr)
                         .setCcapId(ccap.getCcapId())
-                        .setCopsGateId(status.getCopsGateId())
+                        .setTrafficProfile(newGate.getTrafficProfile())
+                        .setClassifiers(newGate.getClassifiers())
+                        .setGateSpec(newGate.getGateSpec())
                         .setCopsGateState("")
-                        .setTimestamp(getNowTimeStamp())
                         .setCopsGateTimeInfo("")
-                        .setCopsGateUsageInfo("")
-                        .setTimestamp(getNowTimeStamp());
+                        .setCopsGateUsageInfo("");
+
+                //
+                // Right now only ServiceClassName traffic Profile is supported. This logic needs to
+                // be updated when the yang traffic-profile is extended to support new types
+                // Override requested Direction using the Ccap configuration information about SCNs and
+                // their configured direction.
+                //
+                final ServiceClassName scn = newGate.getTrafficProfile().getServiceClassName();
+                final ServiceFlowDirection scnDirection = findScnOnCcap(scn, ccap);
+                if (scnDirection == null) {
+                    final String msg =
+                        String.format("SCN %s not found on CCAP %s for %s", scn, ccap.getCcapId(), newGatePathStr);
+                    logger.error(msg);
+                    saveGateError(gateIID, newGatePathStr, msg);
+                    continue;
+                }
+                
+                //
+                // since we may be modifying the contents of the original request GateSpec
+                // to update flow direction (based on the ccap SCN configuration) we need to
+                // rebuild the requested gate spec and replace the existing one in the gate builder
+                //
+                final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder();
+                gateSpecBuilder.setDirection(scnDirection);
+                gateSpecBuilder.setDscpTosMask(newGate.getGateSpec().getDscpTosMask());
+                gateSpecBuilder.setDscpTosOverwrite(newGate.getGateSpec().getDscpTosOverwrite());
+                final GateSpec gateSpec = gateSpecBuilder.build();
+                gateBuilder.setGateSpec(gateSpec);
+
+                //
+                // build the gate to be requested
+                //
+                gateBuilder.setTimestamp(getNowTimeStamp());
+
+                final Gate requestGate = gateBuilder.build();
+
+                //
+                // send gate request to Ccap
+                //
+                PCMMService.GateSendStatus status =
+                        pcmmService.sendGateSet(newGatePathStr, subscriberAddr, requestGate);
+                if (status.didSucceed()) {
+                    gateMap.put(newGatePathStr, requestGate);
+                    gateCcapMap.put(newGatePathStr, ccap.getCcapId());
 
-                if (!status.didSucceed()) {
-                    gateBuilder.setError(Collections.singletonList(status.getMessage()));
-                } else {
+                    //
+                    // inquire as to the status, and implementation info of the requested gate
+                    //
                     PCMMService.GateSendStatus infoStatus = pcmmService.sendGateInfo(newGatePathStr);
 
                     if (infoStatus.didSucceed()) {
+                        //
+                        // update builder with info for operational storage
+                        //
                         gateBuilder.setCopsGateState(
                                 infoStatus.getCopsGateState() + "/" + infoStatus.getCopsGateStateReason())
                                 .setCopsGateTimeInfo(infoStatus.getCopsGateTimeInfo())
-                                .setCopsGateUsageInfo(infoStatus.getCopsGateUsageInfo());
+                                .setCopsGateUsageInfo(infoStatus.getCopsGateUsageInfo())
+                                .setCopsGateId(status.getCopsGateId());
                     } else {
                         List<String> errors = new ArrayList<>(2);
 
@@ -791,19 +829,20 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
                         errors.add(infoStatus.getMessage());
                         gateBuilder.setError(errors);
                     }
-
+                }
+                else {
+                    gateBuilder.setError(Collections.singletonList(status.getMessage()));
                 }
 
                 Gate operationalGate = gateBuilder.build();
 
                 mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIID, operationalGate);
-
             }
 
         }
 
         private void saveGateError(@Nonnull final InstanceIdentifier<Gate> gateIID, @Nonnull final String gatePathStr,
-                @Nonnull final String error) {
+                                   @Nonnull final String error) {
             checkNotNull(gateIID);
             checkNotNull(error);
 
@@ -822,7 +861,7 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
 
         @Override
         protected void handleUpdatedData(final Map<InstanceIdentifier<Gate>, Gate> updatedData,
-                final Map<InstanceIdentifier<Gate>, Gate> originalData) {
+                                         final Map<InstanceIdentifier<Gate>, Gate> originalData) {
             // TODO actually support updates
 
             // update operation not allowed -- restore the original config object and complain
@@ -852,7 +891,7 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
 
         @Override
         protected void handleRemovedData(final Set<InstanceIdentifier<Gate>> removedPaths,
-                final Map<InstanceIdentifier<Gate>, Gate> originalData) {
+                                         final Map<InstanceIdentifier<Gate>, Gate> originalData) {
 
             for (final InstanceIdentifier<Gate> removedGateIID : removedPaths) {
 
@@ -870,8 +909,7 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
                     final PCMMService service = pcmmServiceMap.get(thisCcap.getCcapId());
                     if (service != null) {
                         service.sendGateDelete(gatePathStr);
-                        logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr,
-                                thisGate);
+                        logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr,thisGate);
                     } else {
                         logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - "
                                 + thisCcap);
@@ -945,15 +983,15 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
         }
 
         DateAndTime connectionDateAndTime = getNowTimeStamp();
-        org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.set.connection.output.ccap.ConnectionBuilder
+        org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.set.connection.output.ccap.ConnectionBuilder
                 connectionRpcOutput =
-                new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.set.connection.output.ccap.ConnectionBuilder()
+                new org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.set.connection.output.ccap.ConnectionBuilder()
                         .setConnected(effectiveIsConnected)
                         .setError(outputError)
                         .setTimestamp(connectionDateAndTime);
 
-        org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.set.connection.output.CcapBuilder ccapRpcOutput =
-                new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.set.connection.output.CcapBuilder().setCcapId(
+        org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.set.connection.output.CcapBuilder ccapRpcOutput =
+                new org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.set.connection.output.CcapBuilder().setCcapId(
                         ccapId).setConnection(connectionRpcOutput.build());
 
 
@@ -990,9 +1028,9 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
         PCMMService pcmmService = pcmmServiceMap.get(ccapId);
         Boolean effectiveIsConnected = true;
         String response = null;
-        org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.ccap.ConnectionBuilder
+        org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.poll.connection.output.ccap.ConnectionBuilder
                 connectionRpcOutput =
-                new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.ccap.ConnectionBuilder();
+                new org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.poll.connection.output.ccap.ConnectionBuilder();
 
         if (pcmmService != null) {
             if (pcmmService.getPcmmPdpSocket()) {
@@ -1022,7 +1060,7 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
             CcapBuilder responseCcapBuilder = new CcapBuilder().setCcapId(ccapId).setConnection(connectionOps.build());
 
             connectionRpcOutput =
-                    new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.ccap.ConnectionBuilder()
+                    new org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.poll.connection.output.ccap.ConnectionBuilder()
                             .setConnected(effectiveIsConnected)
                             .setError(outputError)
                             .setTimestamp(connectionDateAndTime);
@@ -1036,8 +1074,8 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
 
         DateAndTime rpcDateAndTime = getNowTimeStamp();
 
-        org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.CcapBuilder ccapRpcOutput =
-                new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.ccap.poll.connection.output.CcapBuilder().setCcapId(
+        org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.poll.connection.output.CcapBuilder ccapRpcOutput =
+                new org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.ccap.poll.connection.output.CcapBuilder().setCcapId(
                         ccapId).setConnection(connectionRpcOutput.build());
 
         CcapPollConnectionOutputBuilder outputBuilder =
@@ -1103,8 +1141,8 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
 
         String rpcResponse = null;
 
-        org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.qos.poll.gates.output.GateBuilder gateOutputBuilder =
-                new org.opendaylight.yang.gen.v1.urn.packetcable.rev151101.qos.poll.gates.output.GateBuilder();
+        org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.qos.poll.gates.output.GateBuilder gateOutputBuilder =
+                new org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.qos.poll.gates.output.GateBuilder();
 
         GateBuilder gateBuilder = new GateBuilder();
 
@@ -1241,80 +1279,109 @@ public class PacketcableProvider implements BindingAwareProvider, AutoCloseable,
                 rpcResponse = gatePathStr + ": Subscriber ID not provided; gate poll not performed";
             } else {
                 //poll all gates for the appId
+                PollAllGatesForApp pollAllGatesForApp = new PollAllGatesForApp(appIid,app);
+                Thread t = new Thread(pollAllGatesForApp);
+                t.start();
+                rpcResponse = appKey.getAppId() + "/: gate subtree poll in progress";
+            }
+        }
 
-                Subscribers subs = app.getSubscribers();
+        DateAndTime rpcDateAndTime = getNowTimeStamp();
 
-                logger.info("qospollgates subscribers: " + subs.toString());
+        QosPollGatesOutputBuilder outputBuilder = new QosPollGatesOutputBuilder().setTimestamp(rpcDateAndTime)
+                .setResponse(rpcResponse)
+                .setGate(gateOutputBuilder.build());
+        return Futures.immediateFuture(RpcResultBuilder.success(outputBuilder.build()).build());
+    }
+    private class PollAllGatesForApp implements Runnable {
 
-                List<Subscriber> subList = subs.getSubscriber();
-                logger.info("qospollgates subList: " + subList.toString());
-                for (Subscriber sub : subList) {
+        private InstanceIdentifier <App> appIid;
+        private App app;
 
-                    //generate active subIid
-                    subscriberId = sub.getSubscriberId();
-                    InstanceIdentifier<Subscriber> subIid = appIid.builder()
-                            .child(Subscribers.class)
-                            .child(Subscriber.class, new SubscriberKey(subscriberId))
-                            .build();
+        private PollAllGatesForApp (InstanceIdentifier <App> appIid, App app) {
+            this.app = app;
+            this.appIid = appIid;
+        }
 
-                    List<Gate> gateList = sub.getGates().getGate();
-                    for (Gate gate : gateList) {
-                        //logger.info("qospollgates active gate: "+gate);
+        @Override
+        public void run() {
 
-                        //generate active gateIid
-                        gateId = gate.getGateId();
-                        InstanceIdentifier<Gate> gateIid =
-                                subIid.builder().child(Gates.class).child(Gate.class, new GateKey(gateId)).build();
+            org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.qos.poll.gates.output.GateBuilder gateOutputBuilder =
+                    new org.opendaylight.yang.gen.v1.urn.packetcable.rev161017.qos.poll.gates.output.GateBuilder();
 
-                        opsGate = readGateFromOperationalDatastore(gateIid);
-                        opsCopsGateId = opsGate.getCopsGateId();
-                        //generate active gatePathStr
-                        gatePathStr = appKey.getAppId() + "/" + subscriberId + "/" + gateId;
-                        if ((!Objects.equals(opsCopsGateId, "")) && (!Objects.equals(opsCopsGateId, null))) {
-                            ccapId = findCcapForSubscriberId(getInetAddress(subscriberId)).getCcapId();
-                            PCMMService pcmmService = pcmmServiceMap.get(ccapId);
-                            //is the CCAP socket open?
-                            if (!pcmmService.getPcmmPdpSocket() && pcmmService.getPcmmCcapClientIsConnected()) {
-                                PCMMService.GateSendStatus status = pcmmService.sendGateInfo(gatePathStr);
-                                DateAndTime gateDateAndTime = getNowTimeStamp();
-                                gateOutputError = Collections.singletonList(status.getMessage());
+            GateBuilder gateBuilder = new GateBuilder();
 
+            //generate appKey
+            AppKey appKey = InstanceIdentifier.keyOf(appIid);
 
-                                gateBuilder.setGateId(gateId)
-                                        .setGatePath(gatePathStr)
-                                        .setCcapId(ccapId)
-                                        .setCopsGateState(
-                                                status.getCopsGateState() + "/" + status.getCopsGateStateReason())
-                                        .setCopsGateTimeInfo(status.getCopsGateTimeInfo())
-                                        .setCopsGateUsageInfo(status.getCopsGateUsageInfo())
-                                        .setCopsGateId(status.getCopsGateId())
-                                        .setError(gateOutputError)
-                                        .setTimestamp(gateDateAndTime);
+            Subscribers subs = app.getSubscribers();
+            logger.info("qospollgates subscribers: " + subs.toString());
 
-                                mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIid, gateBuilder.build());
-                            } else {
-                                logger.info(
-                                        "qospollgates: {}: CCAP socket is down or client disconnected; gate poll not performed",
-                                        ccapId);
-                            }
+            List<Subscriber> subList = subs.getSubscriber();
+            logger.info("qospollgates subList: " + subList.toString());
+
+            for (Subscriber sub : subList) {
+                //generate active subIid
+                String subscriberId = sub.getSubscriberId();
+                InstanceIdentifier<Subscriber> subIid = appIid.builder()
+                        .child(Subscribers.class)
+                        .child(Subscriber.class, new SubscriberKey(subscriberId))
+                        .build();
+
+                List<Gate> gateList = sub.getGates().getGate();
+
+                for (Gate gate : gateList) {
+                    //logger.info("qospollgates active gate: "+gate);
+
+                    //generate active gateIid
+                    String gateId = gate.getGateId();
+                    InstanceIdentifier<Gate> gateIid =
+                            subIid.builder().child(Gates.class).child(Gate.class, new GateKey(gateId)).build();
+
+
+                    Gate opsGate = readGateFromOperationalDatastore(gateIid);
+                    String opsCopsGateId = opsGate.getCopsGateId();
+                    //generate active gatePathStr
+                    String gatePathStr = appKey.getAppId() + "/" + subscriberId + "/" + gateId;
+
+                    if ((!Objects.equals(opsCopsGateId, "")) && (!Objects.equals(opsCopsGateId, null))) {
+                        String ccapId = findCcapForSubscriberId(getInetAddress(subscriberId)).getCcapId();
+                        PCMMService pcmmService = pcmmServiceMap.get(ccapId);
+                        //is the CCAP socket open?
+                        if (!pcmmService.getPcmmPdpSocket() && pcmmService.getPcmmCcapClientIsConnected()) {
+                            PCMMService.GateSendStatus status = pcmmService.sendGateInfo(gatePathStr);
+                            DateAndTime gateDateAndTime = getNowTimeStamp();
+                            List<String> gateOutputError = Collections.singletonList(status.getMessage());
+
+
+                            gateBuilder.setGateId(gateId)
+                                    .setGatePath(gatePathStr)
+                                    .setCcapId(ccapId)
+                                    .setCopsGateState(
+                                            status.getCopsGateState() + "/" + status.getCopsGateStateReason())
+                                    .setCopsGateTimeInfo(status.getCopsGateTimeInfo())
+                                    .setCopsGateUsageInfo(status.getCopsGateUsageInfo())
+                                    .setCopsGateId(status.getCopsGateId())
+                                    .setError(gateOutputError)
+                                    .setTimestamp(gateDateAndTime);
+
+                            mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, gateIid, gateBuilder.build());
                         } else {
-                            //TODO define what happens if a gate is not active.. is nothing ok
-                            logger.info("qospollgates: {}: gate not active; gate poll not performed", gatePathStr);
+                            logger.info(
+                                    "qospollgates: {}: CCAP socket is down or client disconnected; gate poll not performed",
+                                    ccapId);
                         }
+                    } else {
+                        //TODO define what happens if a gate is not active.. is nothing ok
+                        logger.info("qospollgates: {}: gate not active; gate poll not performed", gatePathStr);
                     }
                 }
-                rpcResponse = appKey.getAppId() + "/: gate subtree poll in progress";
             }
         }
 
-        DateAndTime rpcDateAndTime = getNowTimeStamp();
-
-        QosPollGatesOutputBuilder outputBuilder = new QosPollGatesOutputBuilder().setTimestamp(rpcDateAndTime)
-                .setResponse(rpcResponse)
-                .setGate(gateOutputBuilder.build());
-        return Futures.immediateFuture(RpcResultBuilder.success(outputBuilder.build()).build());
     }
 
+
     private DateAndTime getNowTimeStamp() {
         DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
         return new DateAndTime(dateFormat.format(new Date()));