Adding sequential path generation algorithm. 89/28889/4
authorBrady Johnson <[email protected]>
Wed, 28 Oct 2015 13:36:22 +0000 (14:36 +0100)
committerReinaldo Penno <[email protected]>
Tue, 3 Nov 2015 21:32:09 +0000 (21:32 +0000)
- Random generation breaks sfcofl2 vlan demo
- Also added impl code for the service path id RPCs
- Sequential generation Unit tests included

Change-Id: If65a71f4f33cc4a89f9b527366c987967dfc928b
Signed-off-by: Brady Johnson <[email protected]>
sfc-model/src/main/yang/service-path-id.yang
sfc-provider/src/main/java/org/opendaylight/controller/config/yang/config/sfc_provider/impl/SfcProviderModule.java
sfc-provider/src/main/java/org/opendaylight/sfc/provider/SfcProviderRpc.java
sfc-provider/src/main/java/org/opendaylight/sfc/provider/api/SfcServicePathId.java
sfc-provider/src/test/java/org/opendaylight/sfc/provider/api/SfcServicePathIdTest.java

index a8ccde8ea0e1f9074c7b6a27e3d88e733f1f4295..a623f6fd4af5ee20c8a679af37fbe1cc18bf8233 100644 (file)
@@ -75,6 +75,25 @@ module service-path-id {
       "Determines the state of the path-id";
   }
 
+  // Generation algorithm
+
+  typedef generation-algorithm-enum {
+    type enumeration {
+      enum random {
+        value 1;
+        description
+          "Random Path-id generation";
+      }
+      enum sequential {
+        value 2;
+        description
+          "Sequential Path-id generation";
+      }
+    }
+    description
+      "The path-id generation algorithm";
+  }
+
   container service-path-ids {
     config false;
     description
@@ -86,7 +105,7 @@ module service-path-id {
         }
     }
     leaf generation-algorithm {
-       type uint8;
+       type generation-algorithm-enum;
        description
          "The algorithm used to generate path-ids";
     }
@@ -214,4 +233,23 @@ module service-path-id {
       }
     }
   }
+
+  rpc set-generation-algorithm {
+    description
+      "Set the path-id generation algorithm to be used";
+    input {
+      leaf generation-algorithm {
+        type generation-algorithm-enum;
+      }
+    }
+    output {
+      leaf result {
+        type boolean;
+        description
+          "True if the generation-algorithm was set successfully,
+           otherwise false";
+      }
+    }
+  }
+
 }
index 49c22618b2b117386842bbcf860eb8e167637d8c..0c885fc4c9c13e03bebec1b2ee783185fd50d120 100755 (executable)
@@ -13,6 +13,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.sfc.provider.*;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ServicePathIdService;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionService;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainService;
@@ -108,6 +109,11 @@ public class SfcProviderModule extends org.opendaylight.controller.config.yang.c
                         .addRpcImplementation(RenderedServicePathService.class,
                                 sfcProviderRpc);
 
+        final BindingAwareBroker.RpcRegistration<ServicePathIdService> srvPathIdRpcRegistration =
+                getRpcRegistryDependency()
+                        .addRpcImplementation(ServicePathIdService.class,
+                                sfcProviderRpc);
+
         // close()
         final class AutoCloseableSfc implements AutoCloseable {
 
@@ -120,6 +126,7 @@ public class SfcProviderModule extends org.opendaylight.controller.config.yang.c
                 sfRpcRegistration.close();
                 sfcRpcRegistration.close();
                 rspRpcRegistration.close();
+                srvPathIdRpcRegistration.close();
 
                 try
                 {
index 4aa3db229589f39c8adafdfd0a944a7cafb4e12f..9e258bf6ffaacc89f3fb9422193adf60c258a781 100755 (executable)
@@ -26,6 +26,19 @@ import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
+import org.opendaylight.sfc.provider.api.SfcServicePathId;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.AllocatePathIdInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.AllocatePathIdOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.DeletePathIdInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.DeletePathIdOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ReadPathIdInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ReadPathIdOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ReservePathIdRangeInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ReservePathIdRangeOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ServicePathIdService;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.SetGenerationAlgorithmInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.SetGenerationAlgorithmOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.SetGenerationAlgorithmOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName;
@@ -88,7 +101,7 @@ import com.google.common.util.concurrent.Futures;
  * @since 2014-06-30
  */
 
-public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionChainService, RenderedServicePathService {
+public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionChainService, RenderedServicePathService, ServicePathIdService {
 
     private static final Logger LOG = LoggerFactory.getLogger(SfcProviderRpc.class);
     private OpendaylightSfc odlSfc = OpendaylightSfc.getOpendaylightSfcObj();
@@ -369,4 +382,42 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
         return null;
     }
 
+    @Override
+    public Future<RpcResult<ReservePathIdRangeOutput>> reservePathIdRange(
+            ReservePathIdRangeInput input) {
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<ReadPathIdOutput>> readPathId(ReadPathIdInput input) {
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<AllocatePathIdOutput>> allocatePathId(
+            AllocatePathIdInput input) {
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<DeletePathIdOutput>> deletePathId(
+            DeletePathIdInput input) {
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<SetGenerationAlgorithmOutput>> setGenerationAlgorithm(
+            SetGenerationAlgorithmInput input) {
+
+        boolean result = SfcServicePathId.setGenerationAlgorithm(input.getGenerationAlgorithm());
+
+        SetGenerationAlgorithmOutputBuilder setGenerationAlgorithmOutputBuilder =
+                new SetGenerationAlgorithmOutputBuilder();
+        setGenerationAlgorithmOutputBuilder.setResult(result);
+        RpcResultBuilder<SetGenerationAlgorithmOutput> rpcResultBuilder =
+                RpcResultBuilder.success(setGenerationAlgorithmOutputBuilder.build());
+
+        return Futures.immediateFuture(rpcResultBuilder.build());
+    }
+
 }
index c28591cca5ed32130fba91469556ec7b619e05c1..ba9246aaf6342d8af9038a51826f4d6d19a88d85 100644 (file)
@@ -10,7 +10,9 @@
 package org.opendaylight.sfc.provider.api;
 
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.GenerationAlgorithmEnum;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ServicePathIds;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ServicePathIdsBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.service.path.ids.ServicePathId;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.service.path.ids.ServicePathIdBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.service.path.ids.ServicePathIdKey;
@@ -37,8 +39,8 @@ public class SfcServicePathId {
      */
     private final static int MAX_PATH_ID = (int) Math.pow(2, 12) - 1;
     private final static int MIN_PATH_ID = 0;
+    private final static int DEFAULT_GENERATION_ALGORITHM = GenerationAlgorithmEnum.Random.getIntValue();
     private static final Random randomGenerator = new Random();
-    //private static int next_pathid = (randomGenerator.nextInt() % (MAX_PATH_ID + 1));
     private static int next_pathid = 0;
     private final static int num_pathid = MAX_PATH_ID -  MIN_PATH_ID + 1;
 
@@ -54,17 +56,40 @@ public class SfcServicePathId {
      * @return Pathid or error if none available
      */
     public static int generatePathIdRandomIncrements() {
-
         int pathid;
-
         int count = num_pathid;
 
         do {
             next_pathid = next_pathid + (randomGenerator.nextInt(num_pathid) % N) + 1;
             pathid = MIN_PATH_ID + (next_pathid % num_pathid);
 
-            if (check_suitable_pathid(pathid))
+            if (check_suitable_pathid(pathid)) {
+                return pathid;
+            }
+
+            count--;
+        } while (count > 0);
+
+        return -1;
+    }
+
+    /**
+     * Algorithm to sequentially generate pathIds.
+     *
+     * <p>
+     * @return Pathid or error if none available
+     */
+    public static int generatePathIdSequentialIncrements() {
+        int pathid;
+        int count = num_pathid;
+
+        do {
+            next_pathid = next_pathid + 1;
+            pathid = MIN_PATH_ID + next_pathid;
+
+            if (check_suitable_pathid(pathid) && allocate_pathid(pathid)) {
                 return pathid;
+            }
 
             count--;
         } while (count > 0);
@@ -95,7 +120,6 @@ public class SfcServicePathId {
         }
     }
 
-
     /**
      * Check and allocate symmetric Pathid if available
      *
@@ -106,8 +130,18 @@ public class SfcServicePathId {
     public static long check_and_allocate_symmetric_pathid(long pathid) {
         if (SfcConcurrencyAPI.getPathIdLock()) {
             try {
-                long symmetric_id = pathid ^ (1 << 23);
-                if (check_suitable_pathid(symmetric_id) && allocate_pathid(symmetric_id)) {
+                long symmetric_id = -1;
+                GenerationAlgorithmEnum genAlg = getGenerationAlgorithm();
+                if(genAlg == GenerationAlgorithmEnum.Random) {
+                    symmetric_id = pathid ^ (1 << 23);
+                    if(!check_suitable_pathid(symmetric_id)) {
+                        symmetric_id = -1;
+                    }
+                } else if(genAlg == GenerationAlgorithmEnum.Sequential) {
+                    symmetric_id = generatePathIdSequentialIncrements();
+                }
+
+                if ((symmetric_id >= MIN_PATH_ID) && allocate_pathid(symmetric_id)) {
                     return symmetric_id;
                 } else {
                     return -1;
@@ -129,7 +163,14 @@ public class SfcServicePathId {
     public static long check_and_allocate_pathid() {
         if (SfcConcurrencyAPI.getPathIdLock()) {
             try {
-                long pathId = generatePathIdRandomIncrements();
+                long pathId = -1;
+                GenerationAlgorithmEnum genAlg = getGenerationAlgorithm();
+                if(genAlg == GenerationAlgorithmEnum.Random) {
+                    pathId = generatePathIdRandomIncrements();
+                } else if(genAlg == GenerationAlgorithmEnum.Sequential) {
+                    pathId = generatePathIdSequentialIncrements();
+                }
+
                 if ((pathId >= MIN_PATH_ID) && allocate_pathid(pathId)) {
                     return pathId;
                 } else {
@@ -238,4 +279,64 @@ public class SfcServicePathId {
         }
         return false;
     }
+
+    /**
+     * Get the Path-Id Generation-algorithm from the data-store.
+     *
+     * If its not present, create it with the default value.
+     *
+     * <p>
+     * @return generation-algorithm enum value
+     */
+    public static GenerationAlgorithmEnum getGenerationAlgorithm() {
+        InstanceIdentifier<ServicePathIds> spIID =
+                InstanceIdentifier.builder(ServicePathIds.class).build();
+        ServicePathIds servicePathIds =
+                SfcDataStoreAPI.
+                    readTransactionAPI(spIID, LogicalDatastoreType.OPERATIONAL);
+
+        if(servicePathIds == null) {
+            setGenerationAlgorithm(DEFAULT_GENERATION_ALGORITHM);
+            return GenerationAlgorithmEnum.forValue(DEFAULT_GENERATION_ALGORITHM);
+        }
+
+        GenerationAlgorithmEnum genAlgorithm = servicePathIds.getGenerationAlgorithm();
+
+        if(genAlgorithm == null) {
+            setGenerationAlgorithm(DEFAULT_GENERATION_ALGORITHM);
+            return GenerationAlgorithmEnum.forValue(DEFAULT_GENERATION_ALGORITHM);
+        } else {
+            return genAlgorithm;
+        }
+    }
+
+    /**
+     * Set the PathId Generate-algorithm in the data-store.
+     *
+     * <p>
+     * @param genAlgorithm integer value as taken from service-path-id.yang
+     * @return True if successful, otherwise false
+     */
+    public static boolean setGenerationAlgorithm(int genAlgorithm) {
+        return setGenerationAlgorithm(GenerationAlgorithmEnum.forValue(genAlgorithm));
+    }
+
+    /**
+     * Set the PathId Generate-algorithm in the data-store.
+     *
+     * <p>
+     * @param genAlgorithm enum string value as taken from service-path-id.yang
+     * @return True if successful, otherwise false
+     */
+    public static boolean setGenerationAlgorithm(GenerationAlgorithmEnum genAlgorithm) {
+        InstanceIdentifier<ServicePathIds> spIID
+            = InstanceIdentifier.builder(ServicePathIds.class).build();
+
+        ServicePathIdsBuilder servicePathIdsBuilder = new ServicePathIdsBuilder();
+        servicePathIdsBuilder.setGenerationAlgorithm(genAlgorithm);
+
+        return SfcDataStoreAPI.
+                writeMergeTransactionAPI(spIID, servicePathIdsBuilder.build(), LogicalDatastoreType.OPERATIONAL);
+    }
+
 }
index c3fc92e4b9efa2d2225a65fbd541f53facd5cec2..30d80417234284620aef1badfe6ae563f90bdef4 100644 (file)
@@ -10,6 +10,7 @@
 package org.opendaylight.sfc.provider.api;
 
 import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.GenerationAlgorithmEnum;
 
 import java.util.Arrays;
 import java.util.LinkedHashSet;
@@ -164,4 +165,49 @@ public class SfcServicePathIdTest  extends AbstractSfcRendererServicePathAPITest
             assertTrue(SfcServicePathId.check_suitable_pathid(pathId));
         }
     }
+
+    /**
+    *
+    * Method: setGenerationAlgorithm(), check_and_allocate_pathid()
+    *
+    */
+   @Test
+   public void testSequentialGenerationAlgorithm() throws Exception {
+       SfcServicePathId.setGenerationAlgorithm(GenerationAlgorithmEnum.Sequential);
+       long firstPathId = SfcServicePathId.check_and_allocate_pathid();
+       int numPathIds = 20;
+
+       // Verify the pathIds are created sequentially
+       for (long pathId = firstPathId+1; pathId < firstPathId+numPathIds; ++pathId) {
+           assertEquals(SfcServicePathId.check_and_allocate_pathid(), pathId);
+       }
+       // Free the previously allocated pathIds
+       for (long pathId = firstPathId; pathId < firstPathId+numPathIds+1; ++pathId) {
+           assertTrue(SfcServicePathId.free_pathid(pathId));
+       }
+   }
+
+   /**
+   *
+   * Method: setGenerationAlgorithm(), check_and_allocate_pathid(), check_and_allocate_symmetric_pathid()
+   *
+   */
+  @Test
+  public void testSequentialGenerationAlgorithmSymmetric() throws Exception {
+      SfcServicePathId.setGenerationAlgorithm(GenerationAlgorithmEnum.Sequential);
+      long firstPathId = SfcServicePathId.check_and_allocate_pathid();
+      int numPathIds = 40;
+
+      // Verify the pathIds are created sequentially both for the normal and the symmetric cases
+      for (long pathId = firstPathId+1; pathId < firstPathId+numPathIds; pathId+=2) {
+          long id = SfcServicePathId.check_and_allocate_pathid();
+          assertEquals(id, pathId);
+          assertEquals(SfcServicePathId.check_and_allocate_symmetric_pathid(id), pathId+1);
+      }
+      // Free the previously allocated pathIds
+      for (long pathId = firstPathId; pathId < firstPathId+numPathIds+1; ++pathId) {
+          assertTrue(SfcServicePathId.free_pathid(pathId));
+      }
+  }
+
 }