Merge "added yang file describing openflowplugin-impl as CoSS module"
authormichal rehak <mirehak@cisco.com>
Fri, 27 Mar 2015 13:50:19 +0000 (13:50 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 27 Mar 2015 13:50:19 +0000 (13:50 +0000)
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/RequestContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/RequestFutureContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/rpc/RpcContext.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RequestContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcContextImpl.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java

index 18c70bb0a0f32cc8c390edefed936b8f2b1e42fa..ab68756a6660f7aeb80bfba18c858324dccbad39 100644 (file)
@@ -11,11 +11,18 @@ package org.opendaylight.openflowplugin.api.openflow.device;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MessageHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableFeatures;
+
 import java.math.BigInteger;
+
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.util.concurrent.SettableFuture;
+
 import java.util.Collection;
+import java.util.Map;
 import java.util.concurrent.Future;
 
 /**
@@ -96,7 +103,27 @@ public interface DeviceContext extends MessageHandler {
 
     Xid getNextXid();
 
-    <T extends DataObject> Future<RpcResult<T>> sendRequest(DataObject dataObject);
+    <T extends DataObject> Future<RpcResult<T>> sendRequest(Xid xid);
+    
+    /**
+     * Method provides requests map
+     * @return
+     */
+    public Map<Xid, RequestFutureContext> getRequests();
+    
+    /**
+     * Method writes request context into request context map
+     * @param xid
+     * @param requestFutureContext
+     */
+    public void hookRequestCtx(Xid xid, RequestFutureContext requestFutureContext);
+    
+    /**
+     * Method that set future to context in Map
+     * @param xid
+     * @param ofHeader
+     */
+    public void processReply(Xid xid, OfHeader ofHeader);
 
 }
 
index b206e30a8cfa8f15ec2cdcd2412d7abb774a34d0..8d9664b3d973871e0762b59d9eae2576490ebd10 100644 (file)
@@ -16,8 +16,9 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
  * <p/>
  * Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
  */
-public interface RequestContext<T extends DataObject> extends RequestFutureContext, AutoCloseable {
+public interface RequestContext<T extends DataObject> extends RequestFutureContext<T>, AutoCloseable {
 
+    @Override
     void close();
 
 
index 7ad87ea2b1001e4dc6feb3294a121ee8045168ef..dac4ff32a6bd9e5e14895d6f142eaeb78b4a853e 100644 (file)
@@ -23,6 +23,6 @@ public interface RequestFutureContext<T extends DataObject> {
      * @param <T>
      * @return
      */
-    <T> SettableFuture<RpcResult<T>> getFuture();
+    SettableFuture<RpcResult<T>> getFuture();
 
 }
index 14c76bd579e92f1a3eb771fb4211e49757a838e3..651fe6931d469a5811cb913976a790f5740dd19e 100644 (file)
@@ -13,7 +13,6 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import java.util.concurrent.Future;
 
 /**
  * This context is registered with MD-SAL as a routed RPC provider for the inventory node backed by this switch and
@@ -27,33 +26,35 @@ public interface RpcContext extends AutoCloseable {
     <S extends RpcService> void registerRpcServiceImplementation(Class<S> serviceClass, S serviceInstance);
 
     /**
-     *  Method adds request to request queue which has limited quota. After number of requests exceeds quota limit
-     *  future will be done immediately and will contain information about exceeded request quota.
-     *
+     * Method adds request to request queue which has limited quota. After number of requests exceeds quota limit future
+     * will be done immediately and will contain information about exceeded request quota.
+     * 
      * @param data
      */
-    <T extends DataObject> SettableFuture<RpcResult<T>> storeOrFail(RequestContext data);
+    <T extends DataObject> SettableFuture<RpcResult<T>> storeOrFail(RequestContext<T> data);
 
     /**
      * Method for setting request quota value. When the Request Context quota is exceeded, incoming RPCs fail
      * immediately, with a well-defined error.
-     *
+     * 
      * @param maxRequestsPerDevice
      */
     void setRequestContextQuota(int maxRequestsPerDevice);
 
-    void forgetRequestContext(RequestContext requestContext);
+    <T extends DataObject> void forgetRequestContext(RequestContext<T> requestContext);
 
     /**
      * Method provides device context.
+     * 
      * @return
      */
     DeviceContext getDeviceContext();
 
     /**
      * Method returns new request context for current request.
+     * 
      * @return
      */
-    <T extends DataObject> RequestContext createRequestContext();
+    <T extends DataObject> RequestContext<T> createRequestContext();
 
 }
index a195988e5f34291b8fad8c1518ab2dfa37f24205..56deecbe6e78046f4d558ab9c68f6fa2805fa65a 100644 (file)
@@ -7,30 +7,39 @@
  */
 package org.opendaylight.openflowplugin.impl.device;
 
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Future;
+
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestFutureContext;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.api.openflow.device.XidGenerator;
 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
 import org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableFeatures;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import java.math.BigInteger;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Future;
+
+import com.google.common.util.concurrent.SettableFuture;
 
 /**
  *
  */
 public class DeviceContextImpl implements DeviceContext {
+    private Map<Xid, RequestFutureContext> requests =
+            new HashMap<Xid, RequestFutureContext>();
 
     private final Map<SwitchConnectionDistinguisher, ConnectionContext> auxiliaryConnectionContexts = new HashMap<>();
 
+    private XidGenerator xidGenerator = new XidGenerator();
     @Override
     public <M extends ChildOf<DataObject>> void onMessage(M message, RequestContext requestContext) {
         // TODO Auto-generated method stub
@@ -85,13 +94,31 @@ public class DeviceContextImpl implements DeviceContext {
 
     @Override
     public Xid getNextXid() {
-        return null;
+        return xidGenerator.generate();
     }
 
     @Override
-    public <T extends DataObject> Future<RpcResult<T>> sendRequest(final DataObject dataObject) {
+    public <T extends DataObject> Future<RpcResult<T>> sendRequest(Xid xid) {
         return null;
     }
 
+    @Override
+    public Map<Xid, RequestFutureContext> getRequests() {
+        // TODO Auto-generated method stub
+        return requests;
+    }
+
+    @Override
+    public void hookRequestCtx(Xid xid, RequestFutureContext requestFutureContext) {
+        // TODO Auto-generated method stub
+        requests.put(xid, requestFutureContext);
+    }
+
+    @Override
+    public void processReply(Xid xid, OfHeader ofHeader) {
+        // TODO Auto-generated method stub
+        SettableFuture replyFuture = getRequests().get(xid).getFuture();
+        replyFuture.set(ofHeader);
+    }
 
 }
index f5bc9f801f525238441b3f3b6914b3fc9716d22b..3c769bec5cf1a89e449990e3f2a4dc26ab4457f9 100644 (file)
@@ -9,9 +9,13 @@ package org.opendaylight.openflowplugin.impl.device;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestFutureContext;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.device.XidGenerator;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceContextReadyHandler;
@@ -21,9 +25,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDescCaseBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
+import java.util.Map;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 /**
  *
@@ -41,7 +49,7 @@ public class DeviceManagerImpl implements DeviceManager {
         DeviceContextImpl deviceContextImpl = new DeviceContextImpl();
 
         try {
-            FlowCapableNode description = queryDescription(connectionContext, xid.getValue()).get();
+            FlowCapableNode description = queryDescription(connectionContext, deviceContextImpl.getNextXid()).get();
 
         } catch (InterruptedException | ExecutionException e) {
             // TODO Auto-generated catch block
@@ -51,16 +59,16 @@ public class DeviceManagerImpl implements DeviceManager {
 
     /**
      * @param connectionContext
-     * @param nextXid
+     * @param xid
      */
-    private static ListenableFuture<FlowCapableNode> queryDescription(ConnectionContext connectionContext, long nextXid) {
+    private static ListenableFuture<FlowCapableNode> queryDescription(ConnectionContext connectionContext, Xid xid) {
         MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
         builder.setType(MultipartType.OFPMPDESC);
         builder.setVersion(connectionContext.getFeatures().getVersion());
         builder.setFlags(new MultipartRequestFlags(false));
         builder.setMultipartRequestBody(new MultipartRequestDescCaseBuilder()
                 .build());
-        builder.setXid(nextXid);
+        builder.setXid(xid.getValue());
         connectionContext.getConnectionAdapter().multipartRequest(builder.build());
 
         //TODO: involve general wait-for-answer mechanism and return future with complete value
index 0704557f584141dc5eec86a7cf6ea3d8c43fb3a2..d8237c90c26ec845f3a17811c582740206b5ee0b 100644 (file)
@@ -16,7 +16,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 /**
  * @author joe
  */
-public class RequestContextImpl<T extends DataObject> implements RequestContext {
+public class RequestContextImpl<T extends DataObject> implements RequestContext<T> {
 
     private final RpcContext rpcContext;
     private SettableFuture<RpcResult<T>> rpcResultFuture;
index 9a8c19ec3cdc710dda9ea3787160df3107402958..047d44dd06b9b8e5a763fb8a0b8184e0cf6e01d9 100644 (file)
@@ -8,6 +8,9 @@
 package org.opendaylight.openflowplugin.impl.rpc;
 
 import com.google.common.util.concurrent.SettableFuture;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
@@ -18,19 +21,17 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
 
 public class RpcContextImpl implements RpcContext {
 
     final ProviderContext providerContext;
 
     // TODO: add private Sal salBroker
-    private final List<RequestContext> requestContexts = new ArrayList<>();
-    private DeviceContext deviceContext;
+    private final List<RequestContext<? extends DataObject>> requestContexts = new ArrayList<>();
+    private final DeviceContext deviceContext;
     private final List<RoutedRpcRegistration> rpcRegistrations = new ArrayList<>();
-    private final List<RequestContext> synchronizedRequestsList = Collections.synchronizedList(new ArrayList<RequestContext>());
+    private final List<RequestContext<? extends DataObject>> synchronizedRequestsList = Collections
+            .<RequestContext<? extends DataObject>>synchronizedList(new ArrayList<RequestContext<? extends DataObject>>());
 
     private int maxRequestsPerDevice;
 
@@ -41,28 +42,28 @@ public class RpcContextImpl implements RpcContext {
 
     /**
      * @see org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext#registerRpcServiceImplementation(java.lang.Class,
-     * org.opendaylight.yangtools.yang.binding.RpcService)
+     *      org.opendaylight.yangtools.yang.binding.RpcService)
      */
     @Override
     public <S extends RpcService> void registerRpcServiceImplementation(final Class<S> serviceClass,
-                                                                        final S serviceInstance) {
+            final S serviceInstance) {
         rpcRegistrations.add(providerContext.addRoutedRpcImplementation(serviceClass, serviceInstance));
     }
 
     @Override
-    public <T extends DataObject> SettableFuture<RpcResult<T>> storeOrFail(RequestContext requestContext) {
+    public <T extends DataObject> SettableFuture<RpcResult<T>> storeOrFail(final RequestContext<T> requestContext) {
         final SettableFuture<RpcResult<T>> rpcResultFuture = requestContext.getFuture();
 
         if (synchronizedRequestsList.size() < maxRequestsPerDevice) {
             synchronizedRequestsList.add(requestContext);
         } else {
-            RpcResult rpcResult = RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, "", "Device's request queue is full.").build();
+            final RpcResult<T> rpcResult = RpcResultBuilder.<T>failed()
+                    .withError(RpcError.ErrorType.APPLICATION, "", "Device's request queue is full.").build();
             rpcResultFuture.set(rpcResult);
         }
         return rpcResultFuture;
     }
 
-
     /**
      * Unregisters all services.
      *
@@ -84,7 +85,7 @@ public class RpcContextImpl implements RpcContext {
     }
 
     @Override
-    public void forgetRequestContext(final RequestContext requestContext) {
+    public <T extends DataObject> void forgetRequestContext(final RequestContext<T> requestContext) {
         requestContexts.remove(requestContext);
     }
 
@@ -94,7 +95,7 @@ public class RpcContextImpl implements RpcContext {
     }
 
     @Override
-    public <T extends DataObject> RequestContext createRequestContext() {
+    public <T extends DataObject> RequestContext<T> createRequestContext() {
         return new RequestContextImpl<T>(this);
     }
 
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java
new file mode 100644 (file)
index 0000000..4c9fc26
--- /dev/null
@@ -0,0 +1,85 @@
+package org.opendaylight.openflowplugin.impl.device;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.FlowRemovedMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PacketInMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PortStatusMask;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+@RunWith(MockitoJUnitRunner.class)
+public class DeviceContextImplTest {
+    private static final Logger LOG = LoggerFactory
+            .getLogger(DeviceContextImplTest.class);
+    Xid xid;
+    DeviceContextImpl deviceContext;
+    @Mock
+    RequestContext<GetAsyncReply> requestContext;
+
+    @Before
+    public void setUp() {
+        deviceContext = new DeviceContextImpl();
+        xid = deviceContext.getNextXid();
+        SettableFuture<RpcResult<GetAsyncReply>> settableFuture = SettableFuture.create();
+        Mockito.when(requestContext.getFuture()).thenReturn(settableFuture);
+        deviceContext.hookRequestCtx(deviceContext.getNextXid(), requestContext);
+    }
+
+    private GetAsyncOutput createAsyncOutput() {
+        GetAsyncOutputBuilder asyncOutputBuilder = new GetAsyncOutputBuilder();
+        asyncOutputBuilder.setFlowRemovedMask(Collections.<FlowRemovedMask> emptyList());
+        asyncOutputBuilder.setPacketInMask(Collections.<PacketInMask> emptyList());
+        asyncOutputBuilder.setPortStatusMask(Collections.<PortStatusMask> emptyList());
+        asyncOutputBuilder.setVersion(OFConstants.OFP_VERSION_1_3);
+        asyncOutputBuilder.setXid(xid.getValue());
+        return asyncOutputBuilder.build();
+    }
+
+    @Test
+    public void testProcessReply() {
+        GetAsyncOutput asyncOutput = createAsyncOutput();
+        LOG.info("Hooking RequestContext");
+        deviceContext.hookRequestCtx(xid, requestContext);
+        Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid));
+
+        Assert.assertFalse(requestContext.getFuture().isDone());
+        LOG.info("Sending reply from device");
+        deviceContext.processReply(xid, asyncOutput);
+        Assert.assertTrue(requestContext.getFuture().isDone());
+
+        LOG.info("Checking RequestContext.future");
+        try {
+            Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
+            GetAsyncOutput getAsyncOutput = (GetAsyncOutput) object;
+            assertEquals(asyncOutput.getVersion(), getAsyncOutput.getVersion());
+        } catch (InterruptedException | ExecutionException | TimeoutException e) {
+            LOG.error("Test failed when checking RequestContext.future", e);
+            fail("fail");
+        }
+    }
+
+}
index 36ab9182ed8108d5ab10f3ea366573b99a913323..42f241021694d4d754e0b02f9f49c63adc919e14 100644 (file)
@@ -89,5 +89,10 @@ public class DeviceManagerImplTest {
     @Test
     public void testAddRequestContextReadyHandler() {
     }
+    
+    @Test
+    public void testHookRequest() {
+        
+    }
 
 }