Refactor ALTOSPCE and add the rate limiting 16/42716/5
authorXiao Lin <linxiao9292@outlook.com>
Mon, 25 Jul 2016 14:12:15 +0000 (22:12 +0800)
committerXiao Lin <x.shawn.lin@gmail.com>
Sat, 30 Jul 2016 07:15:53 +0000 (15:15 +0800)
Change-Id: Iaf1130c4631dba56cc579b9f160989994af60c59
Signed-off-by: Xiao Lin <x.shawn.lin@gmail.com>
18 files changed:
alto-core/standard-northbound-routes/endpointproperty/impl/src/test/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/AltoNorthboundRouteEndpointpropertyTest.java
alto-extensions/simple-pce/api/pom.xml
alto-extensions/simple-pce/api/src/main/yang/alto-spce.yang
alto-extensions/simple-pce/features/pom.xml
alto-extensions/simple-pce/features/src/main/features/features.xml
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/AltoSpceImpl.java
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/AltoSpceProvider.java
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/algorithm/PathComputation.java
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/EndpointPairAndRequirement.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/FlowInfoKey.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/FlowManager.java
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/InstanceIdentifierUtils.java
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/MeterManager.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteInfoKey.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteInfoValue.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteManager.java [new file with mode: 0644]
alto-extensions/simple-pce/pom.xml
alto-release-features/src/main/features/features.xml

index b4e6b3b761dfd7f9d8938d8b3b759bf419a51180..987f2248cabd31933799861257be247c3f4d4fff 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * Copyright © 2015 Copyright (c) 2015 SNLAB and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
 package org.opendaylight.alto.core.northbound.route.endpointproperty.impl;
 
 import com.fasterxml.jackson.databind.JsonNode;
index 400cdfb36619032b2caa0d2b1a6ebd5bb766e7d9..8b9933049c742fac43821a5b369565ee2e543611 100644 (file)
@@ -29,5 +29,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <groupId>org.opendaylight.mdsal.model</groupId>
       <artifactId>ietf-inet-types-2013-07-15</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-yang-types-20130715</artifactId>
+    </dependency>
   </dependencies>
 </project>
index 7b5b883656b29bb794479f3e1c18c36df5e87e08..f5bbe6744f7dfba493edd275aa18114e363727ab 100644 (file)
@@ -4,21 +4,37 @@ module alto-spce {
     prefix "alto-spce";
 
     import ietf-inet-types {prefix inet;}
+    import ietf-yang-types {prefix yang;}
 
     organization "SNLab.";
-    contact "Jensen Zhang <jingxuan.zhang@gmail.com>";
+    contact "Jensen Zhang <jingxuan.zhang@gmail.com>,
+             Shawn Lin <x.shawn.lin@gmail.com>";
 
-    revision "2015-11-06" {
-        description "Initial revision of alto-spce model. The model is based
+    revision "2016-07-18" {
+        description "The second revision of alto-spce model. The model is based
         on PCEP (https://tools.ietf.org/rfc/rfc5440.txt) but with simplifications.
-        A key simplification is that it does not specify whether it is re-optimization
-        or a new request. We expect the next version to fix the issue.";
+        And we extend it with end to end rate limiting, and getting the network state.";
+    }
+
+    typedef flow-type {
+        type enumeration {
+            enum L2;
+            enum L3;
+        }
     }
 
     typedef error-code-type {
         type enumeration {
             enum OK;
-            enum ERROR;
+            enum COMPUTING_ROUTE_ERROR;
+            enum SETTING_UP_ROUTE_ERROR;
+            enum SETTING_UP_METER_ERROR;
+            enum UNDEFINED_ERROR;
+            enum REMOVING_ROUTE_ERROR;
+            enum REMOVING_METTER_ERROR;
+            enum MISSING_ROUTE_ERROR;
+            enum UPDATING_RATE_LIMITING_ERROR;
+            enum INVALID_INPUT;
         }
     }
 
@@ -29,29 +45,49 @@ module alto-spce {
         }
     }
 
-    rpc alto-spce-setup {
-        description "Given the endpoints, this service computes a path
+    grouping endpoints-group {
+        container endpoints {
+            leaf src {
+                type inet:ipv4-address;
+                mandatory true;
+                description "Source IP address";
+            }
+            leaf dst {
+                type inet:ipv4-address;
+                mandatory true;
+                description "Destination IP address";
+            }
+        }
+    }
+
+    rpc setup-route {
+        description "Given the endpoints, this service computes a route
            satisfying the constraints; among those satisfying the constraints, 
-           it computes the one with the best object metrics. If a path is 
-           found, the service will setup the path by installing flow rules 
+           it computes the one with the best object metrics. If a route is
+           found, the service will setup the route by installing flow rules
            in FRM. This service does not handle the complexity of re-route.";
 
         input {
-            container endpoint {
-                leaf src {
-                    type inet:ipv4-address;
-                    mandatory true;
-                    description "Source IP address";
-                }
-                leaf dst {
-                    type inet:ipv4-address;
-                    mandatory true;
-                    description "Destination IP address";
-                } 
+            uses endpoints-group;
+
+            leaf limited-rate {
+                description "The metric is kbps.";
+                type int32;
             }
+
+            leaf burst-size {
+                description "The metric is kb. The smaller value means rate limiting is more fine grain";
+                type int32;
+            }
+
+            leaf flow-layer {
+                type flow-type;
+            }
+
             leaf-list objective-metrics {
                 type alto-spce-metric;
             }
+
             list constraint-metric {
                 leaf metric {
                     type alto-spce-metric;
@@ -64,21 +100,24 @@ module alto-spce {
                     type uint64;
                 }
             }
+
+
         }
 
         output {
-           leaf path {
-               type string;
-           }
-           leaf error-code {
-               type error-code-type;
-           }
+            leaf route {
+                type string;
+            }
+
+            leaf error-code {
+                type error-code-type;
+            }
         }
     }
 
-    rpc alto-spce-remove {
+    rpc remove-route {
         input {
-            leaf path {
+            leaf route {
                 type string;
             }
         }
@@ -89,4 +128,69 @@ module alto-spce {
             }
         }
     }
+
+    rpc get-route {
+        input {
+            uses endpoints-group;
+        }
+        output {
+            leaf route {
+                type string;
+            }
+            leaf error-code {
+                type error-code-type;
+            }
+        }
+    }
+
+    rpc update-rate-limiting {
+        description "Given the route (source IP and destination IP are all included), and the value of the rate limiting,
+            this service will set the meter with the rate limiting value, and update every related
+            flow entries in switches along this route.";
+
+        input {
+            uses endpoints-group;
+
+            leaf limited-rate {
+                description "The metric is kbps.";
+                type int32;
+            }
+
+            leaf burst-size {
+                description "The metric is kb. The smaller value means rate limiting is more fine grain";
+                type int32;
+            }
+        }
+
+        output {
+            leaf route {
+                type string;
+            }
+
+            leaf error-code {
+                type error-code-type;
+            }
+        }
+    }
+
+    rpc remove-rate-limiting {
+        input {
+            uses endpoints-group;
+
+            leaf route {
+                type string;
+            }
+        }
+
+        output {
+            leaf route {
+                type string;
+            }
+            leaf error-code {
+                type error-code-type;
+            }
+
+        }
+    }
+
 }
index 68f2090a265857ddee93f8a9285aa57374adb46f..ea4c52b68a85c473686fd9143cec2e9dcebeb948 100644 (file)
@@ -25,7 +25,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
     <mdsal.version>1.4.0-SNAPSHOT</mdsal.version>
     <restconf.version>1.4.0-SNAPSHOT</restconf.version>
-    <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+    <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
     <dlux.version>0.4.0-SNAPSHOT</dlux.version>
     <openflow.plugin.version>0.3.0-SNAPSHOT</openflow.plugin.version>
     <l2switch.version>0.4.0-SNAPSHOT</l2switch.version>
@@ -119,7 +119,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <classifier>config</classifier>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
+      <groupId>org.opendaylight.alto.ext</groupId>
       <artifactId>alto-spce-api</artifactId>
       <version>${project.version}</version>
     </dependency>
index 2a02494d6d3296cf2ac1995557bc07fc4e32cc31..367c0e28eddb5b4ad3675c4102d6af67668259b3 100644 (file)
@@ -38,9 +38,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <feature version="${l2switch.version}">odl-l2switch-switch</feature>
     <!-- odl-l2switch-arphandler uses blueprint now, but we still attempt to write data to
     the config subsystem in order to set is-proactive-flood-mode to false. -->
-    <configfile finalname="${configfile.directory}/54-alto-arphandler.xml">
-      mvn:org.opendaylight.alto.spce.network/network-tracker-config/${project.version}/xml/config
-    </configfile>
+<!--    <configfile finalname="${configfile.directory}/54-alto-arphandler.xml">
+      mvn:org.opendaylight.alto.spce.network/network-tracker-config/0.4.0-SNAPSHOT/xml/config
+    </configfile>-->
   </feature>
 
   <feature name='odl-network-tracker-rest' version='${project.version}' description='OpenDaylight :: network-tracker :: REST'>
@@ -57,7 +57,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
 
   <feature name='odl-alto-spce-api' version='${project.version}' description='OpenDaylight :: alto-spce :: api'>
     <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
-    <bundle>mvn:org.opendaylight.alto/alto-spce-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.ext/alto-spce-api/${project.version}</bundle>
   </feature>
   <feature name='odl-alto-spce' version='${project.version}' description='OpenDaylight :: alto-spce'>
     <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
@@ -65,8 +65,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <feature version='${openflow.plugin.version}'>odl-openflowplugin-flow-services</feature>
     <feature version='${project.version}'>odl-alto-spce-api</feature>
     <feature version='${project.version}'>odl-network-tracker</feature>
-    <bundle>mvn:org.opendaylight.alto/alto-spce-impl/${project.version}</bundle>
-    <configfile finalname="${configfile.directory}/alto-spce.xml">mvn:org.opendaylight.alto/alto-spce-impl/${project.version}/xml/config</configfile>
+    <bundle>mvn:org.opendaylight.alto.ext/alto-spce-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/alto-spce.xml">mvn:org.opendaylight.alto.ext/alto-spce-impl/${project.version}/xml/config</configfile>
   </feature>
   <feature name='odl-alto-spce-rest' version='${project.version}' description='OpenDaylight :: alto-spce :: REST'>
     <feature version="${project.version}">odl-alto-spce</feature>
index f203091a8d463da483893275722015319b3fe4ee..cf7ac6dd2c52d752e85c612d80154b3671d4a665 100644 (file)
@@ -8,57 +8,39 @@
 
 package org.opendaylight.alto.spce.impl;
 
-import com.google.common.base.Optional;
 import org.opendaylight.alto.spce.impl.algorithm.PathComputation;
 import org.opendaylight.alto.spce.impl.util.FlowManager;
 import org.opendaylight.alto.spce.impl.util.InventoryReader;
+import org.opendaylight.alto.spce.impl.util.MeterManager;
+import org.opendaylight.alto.spce.impl.util.RouteManager;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-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.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceMetric;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceRemoveInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceRemoveOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceRemoveOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceSetupInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceSetupOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceSetupOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.ErrorCodeType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.ConstraintMetric;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.ConstraintMetricBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.Endpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-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.l2.types.rev130827.EtherType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.AltoSpceMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.AltoSpceService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.ErrorCodeType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.FlowType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.GetRouteInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.GetRouteOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.GetRouteOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRateLimitingInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRateLimitingOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRateLimitingOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRouteInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRouteOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRouteOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.SetupRouteInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.SetupRouteOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.SetupRouteOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.UpdateRateLimitingInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.UpdateRateLimitingOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.UpdateRateLimitingOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.endpoints.group.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.endpoints.group.EndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.setup.route.input.ConstraintMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.setup.route.input.ConstraintMetricBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
@@ -67,57 +49,25 @@ import org.slf4j.LoggerFactory;
 import java.math.BigInteger;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 public class AltoSpceImpl implements AltoSpceService {
 
     private static final Logger LOG = LoggerFactory.getLogger(FlowManager.class);
-    private SalFlowService salFlowService;
-    private NetworkTrackerService networkTrackerService;
-    private DataBroker dataBroker;
     private FlowManager flowManager;
+    private MeterManager meterManager;
     private InventoryReader inventoryReader;
     private PathComputation pathComputation;
+    private RouteManager routeManager;
 
-    public AltoSpceImpl(SalFlowService salFlowService,
+    public AltoSpceImpl(SalMeterService salMeterService,
                         NetworkTrackerService networkTrackerService,
                         DataBroker dataBroker) {
-        this.salFlowService = salFlowService;
-        this.networkTrackerService = networkTrackerService;
-        this.dataBroker = dataBroker;
-        this.flowManager = new FlowManager(salFlowService);
+        this.meterManager = new MeterManager(salMeterService, dataBroker);
+        this.flowManager = new FlowManager(dataBroker);
         this.inventoryReader = new InventoryReader(dataBroker);
         this.pathComputation = new PathComputation(networkTrackerService);
-    }
-
-    public Future<RpcResult<AltoSpceRemoveOutput>> altoSpceRemove(AltoSpceRemoveInput input) {
-        String path = input.getPath();
-        ErrorCodeType errorCode = removePath(path);
-
-        AltoSpceRemoveOutput output = new AltoSpceRemoveOutputBuilder()
-                .setErrorCode(errorCode)
-                .build();
-        return RpcResultBuilder.success(output).buildFuture();
-    }
-
-    public Future<RpcResult<AltoSpceSetupOutput>> altoSpceSetup(AltoSpceSetupInput input) {
-        Endpoint endpoint = input.getEndpoint();
-        List<AltoSpceMetric> altoSpceMetrics = input.getObjectiveMetrics();
-        List<ConstraintMetric> constraintMetrics = compressConstraint(input.getConstraintMetric());
-        List<TpId> path = null;
-        ErrorCodeType errorCode = ErrorCodeType.ERROR;
-
-        if (constraintMetrics != null) {
-            path = computePath(endpoint, altoSpceMetrics, constraintMetrics);
-            errorCode = setupPath(endpoint, path);
-        }
-
-        AltoSpceSetupOutput output = new AltoSpceSetupOutputBuilder()
-                .setPath(pathToString(endpoint, path))
-                .setErrorCode(errorCode)
-                .build();
-        return RpcResultBuilder.success(output).buildFuture();
+        this.routeManager = new RouteManager(pathComputation, inventoryReader, networkTrackerService, flowManager, meterManager, dataBroker);
     }
 
     private List<ConstraintMetric> compressConstraint(List<ConstraintMetric> constraintMetrics) {
@@ -156,189 +106,114 @@ public class AltoSpceImpl implements AltoSpceService {
         return compressedConstraintMetrics;
     }
 
-    private Match parseMacMatch(String path) {
-        String[] tpList = path.split("\\|");
-        MacAddress srcEth = ipToMac(new Ipv4Address(tpList[0]));
-        MacAddress dstEth = ipToMac(new Ipv4Address(tpList[tpList.length - 1]));
-        if (srcEth == null | dstEth == null) {
-            return null;
+    private String showRoute(Endpoints endpoint, List<TpId> path) {
+        String pathString = endpoint.getSrc().getValue();
+        if (path != null) {
+            for (TpId tpId : path) {
+                pathString += "|" + tpId.getValue();
+            }
         }
-        return new MatchBuilder()
-                .setEthernetMatch(new EthernetMatchBuilder()
-                        .setEthernetSource(new EthernetSourceBuilder()
-                                .setAddress(srcEth)
-                                .build())
-                        .setEthernetDestination(new EthernetDestinationBuilder()
-                                .setAddress(dstEth)
-                                .build())
-                        .build())
-                .build();
+        pathString += "|" + endpoint.getDst().getValue();
+        return pathString;
     }
 
-    private Match parseIpMatch(String path) {
-        String[] tpList = path.split("\\|");
-        Ipv4Prefix srcIp = new Ipv4Prefix(tpList[0] + "/32");
-        Ipv4Prefix dstIp = new Ipv4Prefix(tpList[tpList.length - 1] + "/32");
-        if (srcIp == null | dstIp == null) {
-            return null;
+    @Override
+    public Future<RpcResult<UpdateRateLimitingOutput>> updateRateLimiting(UpdateRateLimitingInput input) {
+        ErrorCodeType errorCodeType = this.routeManager.updateRateLimiting(input.getEndpoints(), input.getLimitedRate(), input.getBurstSize());
+        UpdateRateLimitingOutputBuilder builder = new UpdateRateLimitingOutputBuilder().setErrorCode(errorCodeType);
+        if (errorCodeType==ErrorCodeType.OK) {
+            builder.setRoute(showRoute(input.getEndpoints(),this.routeManager.getRoute(input.getEndpoints())));
         }
-        return new MatchBuilder()
-                .setLayer3Match(new Ipv4MatchBuilder()
-                        .setIpv4Source(srcIp)
-                        .setIpv4Destination(dstIp)
-                        .build())
-                .setEthernetMatch(new EthernetMatchBuilder()
-                        .setEthernetType(new EthernetTypeBuilder()
-                                .setType(new EtherType(0x0800L))
-                                .build())
-                        .build())
-                .build();
+        return RpcResultBuilder.success(builder.build()).buildFuture();
     }
 
-    private List<TpId> parseTpIds(String path) {
-        List<TpId> tpIds = new LinkedList<>();
-        String[] tpList = path.split("\\|");
-        for (int i = 1; i < tpList.length -1; i++) {
-            tpIds.add(new TpId(tpList[i]));
+    @Override
+    public Future<RpcResult<RemoveRateLimitingOutput>> removeRateLimiting(RemoveRateLimitingInput input) {
+        ErrorCodeType errorCodeType = this.routeManager.removeRateLimiting(input.getEndpoints());
+        RemoveRateLimitingOutputBuilder builder = new RemoveRateLimitingOutputBuilder().setErrorCode(errorCodeType);
+        if (errorCodeType==ErrorCodeType.OK) {
+            builder.setRoute(showRoute(input.getEndpoints(),this.routeManager.getRoute(input.getEndpoints())));
         }
-        return tpIds;
+        return RpcResultBuilder.success(builder.build()).buildFuture();
     }
 
-    private ErrorCodeType removePath(String path) {
-        List<TpId> tpIds = parseTpIds(path);
-        Match macMatch = parseMacMatch(path);
-        Match ipMatch = parseIpMatch(path);
-        if (macMatch == null | ipMatch == null) {
-            return ErrorCodeType.ERROR;
-        }
-        try {
-            for (TpId tpId : tpIds) {
-                NodeRef nodeRef =
-                        new NodeRef(InstanceIdentifier.builder(Nodes.class)
-                                .child(Node.class, new NodeKey(
-                                        new NodeId(tpId.getValue().substring(0, tpId.getValue().lastIndexOf(":")))))
-                                .build());
-                this.salFlowService.removeFlow(new RemoveFlowInputBuilder()
-                        .setMatch(macMatch)
-                        .setNode(nodeRef)
-                        .setTransactionUri(tpId)
-                        .build()
-                );
-                this.salFlowService.removeFlow(new RemoveFlowInputBuilder()
-                        .setMatch(ipMatch)
-                        .setNode(nodeRef)
-                        .build()
-                );
-            }
-        } catch (Exception e) {
-            LOG.info("Exception occurs when remove a path: " + e.getMessage());
-            return ErrorCodeType.ERROR;
-        }
-        return ErrorCodeType.OK;
-    }
+    @Override
+    public Future<RpcResult<RemoveRouteOutput>> removeRoute(RemoveRouteInput input) {
+        String route = input.getRoute();
+        String src = route.substring(0, route.indexOf('|'));
+        String dst = route.substring(route.lastIndexOf('|')+1);
+        Endpoints endpoints = new EndpointsBuilder()
+                .setSrc(new Ipv4Address(src))
+                .setDst(new Ipv4Address(dst))
+                .build();
 
-    private List<TpId> computePath(Endpoint endpoint,
-                               List<AltoSpceMetric> altoSpceMetrics,
-                               List<ConstraintMetric> constraintMetrics) {
-        List<TpId> path = null;
-        TpId srcTpId = getAttachTp(endpoint.getSrc());
-        TpId dstTpId = getAttachTp(endpoint.getDst());
-        Topology topology = getTopology();
+        ErrorCodeType errorCodeType = this.routeManager.removeRoute(endpoints);
 
-        try {
-            if (altoSpceMetrics.get(0) == AltoSpceMetric.Bandwidth) {
-                path = pathComputation.maxBandwidthPath(srcTpId, dstTpId, topology, constraintMetrics);
-            } else if (altoSpceMetrics.get(0) == AltoSpceMetric.Hopcount) {
-                path = pathComputation.shortestPath(srcTpId, dstTpId, topology, constraintMetrics);
-            }
-        } catch (Exception e) {
-            LOG.info("Exception occurs when compute path: " + e.getMessage());
+        RemoveRouteOutputBuilder outputBuilder = new RemoveRouteOutputBuilder();
+        outputBuilder.setErrorCode(errorCodeType);
+        return RpcResultBuilder.success(outputBuilder.build()).buildFuture();
+    }
+
+    @Override
+    public Future<RpcResult<SetupRouteOutput>> setupRoute(SetupRouteInput input) {
+        if (null == input.getFlowLayer() || null == input.getEndpoints()) {
+            SetupRouteOutputBuilder outputBuilder = new SetupRouteOutputBuilder();
+            outputBuilder.setErrorCode(ErrorCodeType.INVALIDINPUT);
+            return RpcResultBuilder.success(outputBuilder.build()).buildFuture();
         }
 
-        return path;
-    }
+        Endpoints endpoints = input.getEndpoints();
+        Integer burstSize =  input.getBurstSize();
+        Integer limitedRate = input.getLimitedRate();
+        FlowType flowLayer = input.getFlowLayer();
+        List<AltoSpceMetric> altoSpceMetrics = input.getObjectiveMetrics();
+        List<ConstraintMetric> constraintMetrics = compressConstraint(input.getConstraintMetric());
 
-    private TpId getAttachTp(Ipv4Address src) {
-        return this.inventoryReader.getNodeConnectorByMac(ipToMac(src));
-    }
+        List<TpId> route;
+        ErrorCodeType errorCode;
 
-    private MacAddress ipToMac(Ipv4Address src) {
-        MacAddress mac = null;
-        AltoSpceGetMacByIpInput input = new AltoSpceGetMacByIpInputBuilder()
-                .setIpAddress(src.getValue())
-                .build();
-        Future<RpcResult<AltoSpceGetMacByIpOutput>> result = this.networkTrackerService.altoSpceGetMacByIp(input);
-        try {
-            AltoSpceGetMacByIpOutput output = result.get().getResult();
-            mac = new MacAddress(output.getMacAddress());
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.info("Exception occurs when convert ip to mac: " + e.getMessage());
-        }
-        return mac;
-    }
+        route = this.routeManager.computeRoute(endpoints, altoSpceMetrics, constraintMetrics);
 
-    private ErrorCodeType setupPath(Endpoint endpoint, List<TpId> path) {
-        if (path == null) {
-            LOG.info("Setup Error: path is null.");
-            return ErrorCodeType.ERROR;
+        if (route == null) {
+            errorCode = ErrorCodeType.COMPUTINGROUTEERROR;
+            SetupRouteOutput output = new SetupRouteOutputBuilder()
+                    .setErrorCode(errorCode).build();
+            return RpcResultBuilder.success(output).buildFuture();
         }
 
-        try {
-            Ipv4Address srcIp = endpoint.getSrc();
-            Ipv4Address dstIp = endpoint.getDst();
-            MacAddress srcMac = ipToMac(srcIp);
-            MacAddress dstMac = ipToMac(dstIp);
-            List<NodeConnectorRef> nodeConnectorRefs = new LinkedList<>();
-            for (TpId tpid : path) {
-                String nc_value = tpid.getValue();
-                InstanceIdentifier<NodeConnector> ncid = InstanceIdentifier.builder(Nodes.class)
-                        .child(
-                                Node.class,
-                                new NodeKey(new NodeId(nc_value.substring(0, nc_value.lastIndexOf(':')))))
-                        .child(
-                                NodeConnector.class,
-                                new NodeConnectorKey(new NodeConnectorId(nc_value)))
-                        .build();
-                nodeConnectorRefs.add(new NodeConnectorRef(ncid));
-            }
-            LOG.info("Setup a path: srcIp=" + srcIp.getValue() + ", dstIp=" + dstIp.getValue());
-            LOG.info("Setup a path: srcMac=" + srcMac.getValue() + ", dstMac=" + dstMac.getValue());
-            this.flowManager.addFlowByPath(srcIp, dstIp, nodeConnectorRefs);
-            this.flowManager.addFlowByPath(srcMac, dstMac, nodeConnectorRefs);
-        } catch (Exception e) {
-            LOG.info("Exception occurs when setup a path: " + e.getMessage());
-            return ErrorCodeType.ERROR;
+        if (burstSize == null || limitedRate == null || burstSize.intValue() < 0 || limitedRate.intValue() < 0) {
+            errorCode = this.routeManager.setupRoute(endpoints, route, flowLayer, -1, -1);
+        } else {
+            errorCode = this.routeManager.setupRoute(endpoints, route, flowLayer, limitedRate, burstSize);
         }
-        return ErrorCodeType.OK;
-    }
 
-    private String pathToString(Endpoint endpoint, List<TpId> path) {
-        String pathString = endpoint.getSrc().getValue();
-        if (path != null) {
-            for (TpId tpId : path) {
-                pathString += "|" + tpId.getValue();
-            }
+        if (errorCode != ErrorCodeType.OK) {
+            SetupRouteOutput output = new SetupRouteOutputBuilder()
+                    .setErrorCode(errorCode).build();
+            return RpcResultBuilder.success(output).buildFuture();
+        } else {
+            SetupRouteOutput output = new SetupRouteOutputBuilder()
+                    .setRoute(showRoute(endpoints, route))
+                    .setErrorCode(errorCode)
+                    .build();
+            return RpcResultBuilder.success(output).buildFuture();
         }
-        pathString += "|" + endpoint.getDst().getValue();
-        return pathString;
     }
 
-    private Topology getTopology() {
-        try {
-            ReadOnlyTransaction readTx = this.dataBroker.newReadOnlyTransaction();
-
-            InstanceIdentifier<Topology> topologyInstanceIdentifier = InstanceIdentifier
-                    .builder(NetworkTopology.class)
-                    .child(Topology.class, new TopologyKey(new TopologyId("flow:1")))
-                    .build();
-
-            Optional<Topology> dataFuture = readTx.read(LogicalDatastoreType.OPERATIONAL,
-                    topologyInstanceIdentifier).get();
-
-            return dataFuture.get();
-        } catch (Exception e) {
-            LOG.info("Exception occurs when get topology: " + e.getMessage());
+    @Override
+    public Future<RpcResult<GetRouteOutput>> getRoute(GetRouteInput input) {
+        GetRouteOutputBuilder builder = new GetRouteOutputBuilder();
+        if (null == input || null == input.getEndpoints()) {
+            builder.setErrorCode(ErrorCodeType.INVALIDINPUT);
+        } else {
+            builder.setErrorCode(ErrorCodeType.OK);
+            List<TpId> route = this.routeManager.getRoute(input.getEndpoints());
+            if (null == route) {
+                builder.setRoute("ROUTE_HAVE_NOT_BEEN_SET_UP");
+            } else {
+                builder.setRoute(showRoute(input.getEndpoints(), route));
+            }
         }
-        return null;
+        return RpcResultBuilder.success(builder.build()).buildFuture();
     }
 }
index 9bb536808f0df7edd76c9c4c579e56c519ae48db..527d263e2c419d52e2600a94e70d1379b5395369 100644 (file)
@@ -12,8 +12,10 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceService;
+/*import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceService;*/
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.AltoSpceService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -27,9 +29,10 @@ public class AltoSpceProvider implements BindingAwareProvider, AutoCloseable {
     public void onSessionInitiated(ProviderContext session) {
         LOG.info("AltoSpceProvider Session Initiated!");
         SalFlowService salFlowService = session.getRpcService(SalFlowService.class);
+        SalMeterService salMeterServer = session.getRpcService(SalMeterService.class);
         NetworkTrackerService networkTrackerService = session.getRpcService(NetworkTrackerService.class);
         DataBroker dataBroker = session.getSALService(DataBroker.class);
-        altoSpceService = session.addRpcImplementation(AltoSpceService.class, new AltoSpceImpl(salFlowService, networkTrackerService, dataBroker));
+        altoSpceService = session.addRpcImplementation(AltoSpceService.class, new AltoSpceImpl(salMeterServer,networkTrackerService, dataBroker));
     }
 
     @Override
index 6cb18e21345ebfc4d56c9e452466cbb503c69eec..ca3dd4586155fa3e7f467a387215353272c35cfd 100644 (file)
@@ -12,8 +12,10 @@ import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath;
 import edu.uci.ics.jung.graph.Graph;
 import edu.uci.ics.jung.graph.SparseMultigraph;
 import edu.uci.ics.jung.graph.util.EdgeType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceMetric;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.ConstraintMetric;
+/*import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.ConstraintMetric;*/
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.AltoSpceMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.setup.route.input.ConstraintMetric;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthOutput;
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/EndpointPairAndRequirement.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/EndpointPairAndRequirement.java
new file mode 100644 (file)
index 0000000..9a358b3
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2015 Copyright (c) 2015 SNLAB and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.alto.spce.impl.util;
+
+public class EndpointPairAndRequirement {
+    private String src;
+    private String dst;
+    private Long dropRate;
+    private Long burstSize;
+    public EndpointPairAndRequirement(String src, String dst, Long dropRate, Long burstSize) {
+        this.src = src;
+        this.dst = dst;
+        this.dropRate = dropRate;
+        this.burstSize = burstSize;
+    }
+
+    public int hashCode() {
+        return this.burstSize.hashCode()+this.dropRate.hashCode()+this.src.hashCode()+this.dst.hashCode();
+    }
+
+    public boolean equals(Object obj) {
+        if (null == obj) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        EndpointPairAndRequirement epr = (EndpointPairAndRequirement) obj;
+        if (null == epr.src || null == epr.dst || null == epr.dropRate || null == epr.burstSize
+                || !(this.src.equals(epr.src)) || !(this.dst.equals(epr.dst))
+                || !(this.dropRate.equals(epr.dropRate)) || !(this.burstSize.equals(epr.burstSize))) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/FlowInfoKey.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/FlowInfoKey.java
new file mode 100644 (file)
index 0000000..951415b
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2015 Copyright (c) 2015 SNLAB and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.alto.spce.impl.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FlowInfoKey {
+    private InstanceIdentifier<Node> nodeIID;
+    private Match match;
+
+    public FlowInfoKey(InstanceIdentifier<Node> nodeIID, Match match) {
+        this.nodeIID = nodeIID;
+        this.match = match;
+    }
+
+    public int hashCode() {
+        return this.nodeIID.hashCode()+this.match.hashCode();
+    }
+
+    public boolean equals(Object obj) {
+        if (null == obj) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        FlowInfoKey flowInfoKey = (FlowInfoKey) obj;
+
+        if (null == flowInfoKey.nodeIID || null == flowInfoKey.match
+                || !(this.nodeIID.toString().equals(flowInfoKey.nodeIID.toString()))
+                || !(this.match.toString().equals(flowInfoKey.match.toString()))
+        ) {
+            return false;
+        }
+
+        return true;
+    }
+
+}
index 905f849eb057cd397deef20facf7c99f15db2925..e957bb7bfffc96a8abb3d6fb554c16f10735530d 100644 (file)
@@ -9,33 +9,36 @@
 package org.opendaylight.alto.spce.impl.util;
 
 import com.google.common.collect.ImmutableList;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 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.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.MeterBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
@@ -44,6 +47,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
@@ -52,259 +56,322 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicLong;
 
 public class FlowManager {
     private static final Logger LOG = LoggerFactory.getLogger(FlowManager.class);
-    private SalFlowService salFlowService;
+    private DataBroker dataBroker;
     private short flowTableId;
     private int flowPriority;
     private int flowIdleTimeout;
     private int flowHardTimeout;
 
-    private AtomicLong flowIdInc = new AtomicLong();
-    private AtomicLong flowCookieInc = new AtomicLong(0x2a00000000000000L);
+
+    protected HashMap<FlowInfoKey, InstanceIdentifier<Flow>> flowInfo = new HashMap<>();
+
+    private AtomicLong flowIdInc = new AtomicLong(10L);
+    private AtomicLong flowCookieInc = new AtomicLong(0x3a00000000000000L);
     private final short DEFAULT_TABLE_ID = 0;
     private final Integer DEFAULT_PRIORITY = 20;
-    private final Integer DEFAULT_HARD_TIMEOUT = 3600;
-    private final Integer DEFAULT_IDLE_TIMEOUT = 1800;
+    private final Integer DEFAULT_HARD_TIMEOUT = 0;
+    private final Integer DEFAULT_IDLE_TIMEOUT = 0;
     private final Long OFP_NO_BUFFER = Long.valueOf(4294967295L);
 
-    public FlowManager(SalFlowService salFLowService) {
-        this.salFlowService = salFLowService;
+    private final String DEFAULT_SUBNET_MASK = "/32";
+    private final Long IP_ETHER_TYPE = 0x0800L;
+    private final Long NO_METER_SPECIFIED = -1L;
+
+    public FlowManager(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
         setFlowTableId(DEFAULT_TABLE_ID);
         setFlowPriority(DEFAULT_PRIORITY);
         setFlowIdleTimeout(DEFAULT_IDLE_TIMEOUT);
         setFlowHardTimeout(DEFAULT_HARD_TIMEOUT);
        }
 
-    public void setFlowTableId(short flowTableId) {
-        this.flowTableId = flowTableId;
+    private Match createMacMatch(MacAddress srcMac, MacAddress dstMac) {
+        EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder();
+        if (dstMac != null) {
+            ethernetMatchBuilder.setEthernetDestination(new EthernetDestinationBuilder()
+                    .setAddress(dstMac)
+                    .build());
+        }
+        if (srcMac != null) {
+            ethernetMatchBuilder.setEthernetSource(new EthernetSourceBuilder()
+                    .setAddress(srcMac)
+                    .build());
+        }
+        EthernetMatch ethernetMatch = ethernetMatchBuilder.build();
+        if (ethernetMatch != null) {
+            return new MatchBuilder()
+                    .setEthernetMatch(ethernetMatch)
+                    .build();
+        } else {
+            return null;
+        }
     }
 
-    public void setFlowPriority(int flowPriority) {
-        this.flowPriority = flowPriority;
+    protected Match createIpv4Match(Ipv4Address srcIP, Ipv4Address dstIP) {
+        Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder();
+        if (dstIP != null) {
+            ipv4MatchBuilder.setIpv4Destination(new Ipv4Prefix(dstIP.getValue() + DEFAULT_SUBNET_MASK));
+        }
+        if(srcIP != null) {
+            ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(srcIP.getValue() + DEFAULT_SUBNET_MASK));
+        }
+        Layer3Match layer3Match = ipv4MatchBuilder.build();
+        if (layer3Match != null) {
+            return new MatchBuilder()
+                    .setLayer3Match(layer3Match)
+                    .setEthernetMatch(new EthernetMatchBuilder()
+                            .setEthernetType(new EthernetTypeBuilder()
+                                    .setType(new EtherType(IP_ETHER_TYPE))
+                                    .build())
+                            .build())
+                    .build();
+
+        } else {
+            return null;
+        }
     }
 
-    public void setFlowIdleTimeout(int flowIdleTimeout) {
-        this.flowIdleTimeout = flowIdleTimeout;
+    private Instruction createApplyActionsInstruction(Uri dstPortUri, int order) {
+        Action outputToControllerAction = new ActionBuilder()
+                .setOrder(0)
+                .setAction(new OutputActionCaseBuilder()
+                        .setOutputAction(new OutputActionBuilder()
+                                .setMaxLength(0xffff)
+                                .setOutputNodeConnector(dstPortUri)
+                                .build())
+                        .build())
+                .build();
+        ApplyActions applyActions = new ApplyActionsBuilder().setAction(ImmutableList.of(outputToControllerAction))
+                .build();
+        return new InstructionBuilder()
+                .setOrder(order)
+                .setInstruction(new ApplyActionsCaseBuilder()
+                        .setApplyActions(applyActions)
+                        .build())
+                .build();
     }
 
-    public void setFlowHardTimeout(int flowHardTimeout) {
-        this.flowHardTimeout = flowHardTimeout;
+    private Instruction createMeterInstruction(long meterId, int order) {
+        MeterBuilder meterBuilder = new MeterBuilder()
+                .setMeterId(new MeterId(meterId));
+        return new InstructionBuilder()
+                .setOrder(order)
+                .setInstruction(new MeterCaseBuilder()
+                        .setMeter(meterBuilder.build())
+                        .build())
+                .build();
     }
 
-    public void addMacToMacFlow(MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destNodeConnectorRef) {
-
-        if(sourceMac != null && destMac.equals(sourceMac)) {
-            LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
-            return;
+    private Instructions createInstructions(NodeConnectorRef dstPort, Long meterId) {
+        List<Instruction> instructionList = new LinkedList<>();
+        Uri dstPortUri = dstPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+        if (meterId != null && meterId > 0) {
+            instructionList.add(createMeterInstruction(meterId, 0));
+            instructionList.add(createApplyActionsInstruction(dstPortUri, 1));
+        } else {
+            instructionList.add(createApplyActionsInstruction(dstPortUri, 0));
         }
+        return new InstructionsBuilder()
+                .setInstruction(instructionList)
+                .build();
+    }
 
-        TableKey flowTableKey = new TableKey((short) flowTableId);
-
-        InstanceIdentifier<Flow> flowPath = buildFlowPath(destNodeConnectorRef, flowTableKey);
-
-        Flow flowBody = createMacToMacFlow(flowTableKey.getId(), flowPriority, sourceMac, destMac, destNodeConnectorRef);
-
-        writeFlowToConfigData(flowPath, flowBody);
+    private Flow createFlow(FlowId flowId, String flowName, Short tableId, int priority, Match match, Instructions instructions) {
+        return new FlowBuilder()
+                .setId(flowId)
+                .setFlowName(flowName)
+                .setTableId(tableId)
+                .setMatch(match)
+                .setInstructions(instructions)
+                .setPriority(priority)
+                .setBufferId(OFP_NO_BUFFER)
+                .setHardTimeout(DEFAULT_HARD_TIMEOUT)
+                .setIdleTimeout(DEFAULT_IDLE_TIMEOUT)
+                .setFlags(new FlowModFlags(false,false,false,false,false))
+                .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
+                .build();
     }
 
-    public void addIpToIpFlow(Ipv4Address sourceIp, Ipv4Address destIp, NodeConnectorRef destNodeConnectorRef) {
+    private Flow createMacToMacFlow(FlowId flowId, Short tableId, int priority,
+                                    MacAddress srcMac, MacAddress dstMac, Long meterId, NodeConnectorRef dstPort) {
+        String flowName = srcMac.getValue() + "|" + dstMac.getValue();
 
-        if(sourceIp != null && destIp.equals(sourceIp)) {
-            LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
-            return;
-        }
+        Match match = createMacMatch(srcMac, dstMac);
 
-        TableKey flowTableKey = new TableKey((short) flowTableId);
+        Instructions instructions;
+        if (meterId != null && meterId > 0) {
+            instructions = createInstructions(dstPort, meterId);
+        } else {
+            instructions = createInstructions(dstPort, NO_METER_SPECIFIED);
+        }
 
-        InstanceIdentifier<Flow> flowPath = buildFlowPath(destNodeConnectorRef, flowTableKey);
+        return createFlow(flowId, flowName, tableId, priority, match, instructions);
+    }
 
-        Flow flowBody = createIpv4ToIpv4Flow(flowTableKey.getId(), flowPriority, sourceIp, destIp, destNodeConnectorRef);
+    private Flow createIpv4ToIpv4Flow(FlowId flowId, Short tableId, int priority,
+                                      Ipv4Address srcIp, Ipv4Address dstIp, Long meterId, NodeConnectorRef dstPort) {
+        String flowName = srcIp.getValue() + "|" + dstIp.getValue();
 
-        LOG.info("writeFlow: " + flowBody.toString());
+        Match match = createIpv4Match(srcIp, dstIp);
 
-        try {
-            Future<RpcResult<AddFlowOutput>> result = writeFlowToConfigData(flowPath, flowBody);
-            AddFlowOutput output = result.get().getResult();
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.info("WriteFlow Error: " + e.getMessage());
+        Instructions instructions;
+        if (meterId != null && meterId > 0) {
+            instructions = createInstructions(dstPort, meterId);
+        } else {
+            instructions = createInstructions(dstPort, NO_METER_SPECIFIED);
         }
-    }
 
-    public void addFlowByPath(MacAddress sourceMac, MacAddress destMac, List<NodeConnectorRef> path) {
+        return createFlow(flowId,flowName, tableId, priority, match, instructions);
+    }
 
-        if(sourceMac != null && destMac.equals(sourceMac)) {
-            LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
-            return;
-        }
 
-        for (NodeConnectorRef nc : path) {
-            addMacToMacFlow(sourceMac, destMac, nc);
-        }
+    public void setFlowTableId(short flowTableId) {
+        this.flowTableId = flowTableId;
     }
 
-    public void addFlowByPath(Ipv4Address sourceIp, Ipv4Address destIp, List<NodeConnectorRef> path) {
-
-        if(sourceIp != null && destIp.equals(sourceIp)) {
-            LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
-            return;
-        }
+    public void setFlowPriority(int flowPriority) {
+        this.flowPriority = flowPriority;
+    }
 
-        for (NodeConnectorRef nc : path) {
-            addIpToIpFlow(sourceIp, destIp, nc);
-        }
+    public void setFlowIdleTimeout(int flowIdleTimeout) {
+        this.flowIdleTimeout = flowIdleTimeout;
     }
 
-    private InstanceIdentifier<Flow> buildFlowPath(NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) {
+    public void setFlowHardTimeout(int flowHardTimeout) {
+        this.flowHardTimeout = flowHardTimeout;
+    }
 
-        FlowId flowId = new FlowId(String.valueOf(flowIdInc.getAndIncrement()));
-        FlowKey flowKey = new FlowKey(flowId);
+    public void removeFlow(MacAddress srcMac, MacAddress dstMac, NodeConnectorRef dstNodeConnectorRef) {
+        LOG.info("Removing Flow from " + dstNodeConnectorRef.toString());
+        TableKey flowTableKey = new TableKey(flowTableId);
+        InstanceIdentifier<Flow> flowPath = buildFlowPath(createMacMatch(srcMac, dstMac), dstNodeConnectorRef, flowTableKey);
+        LOG.info("Removed flow path: " + flowPath.toString());
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
 
-        return InstanceIdentifierUtils.generateFlowInstanceIdentifier(nodeConnectorRef, flowTableKey, flowKey);
+        writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowPath);
+        try {
+            writeTransaction.submit().checkedGet();
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("Transaction failed: {}", e.toString());
+        }
+        LOG.info("Transaction succeeded");
+        this.flowInfo.remove(new FlowInfoKey(InstanceIdentifierUtils.generateNodeInstanceIdentifier(dstNodeConnectorRef), createMacMatch(srcMac, dstMac)));
     }
 
-    private Flow createMacToMacFlow(Short tableId, int priority,
-                                    MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destPort) {
+    public void removeFlow(Ipv4Address srcIp, Ipv4Address dstIp, NodeConnectorRef dstNodeConnectorRef) {
+        LOG.info("Removing Flow from " + dstNodeConnectorRef.toString());
+        TableKey flowTableKey = new TableKey(flowTableId);
+        InstanceIdentifier<Flow> flowPath = buildFlowPath(createIpv4Match(srcIp, dstIp), dstNodeConnectorRef, flowTableKey);
+        LOG.info("Removed flow path: " + flowPath.toString());
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
 
-        FlowBuilder macToMacFlow = new FlowBuilder() //
-                .setTableId(tableId) //
-                .setFlowName("mac2mac");
+        writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowPath);
+        try {
+            writeTransaction.submit().checkedGet();
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("Transaction failed: {}", e.toString());
+        }
+        LOG.info("Transaction succeeded");
+        this.flowInfo.remove(new FlowInfoKey(InstanceIdentifierUtils.generateNodeInstanceIdentifier(dstNodeConnectorRef), createIpv4Match(srcIp, dstIp)));
+    }
 
-        macToMacFlow.setId(new FlowId(Long.toString(macToMacFlow.hashCode())));
+    public void writeFlow(MacAddress srcMac, MacAddress dstMac, NodeConnectorRef dstNodeConnectorRef, Long meterId) {
 
-        EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder() //
-                .setEthernetDestination(new EthernetDestinationBuilder() //
-                        .setAddress(destMac) //
-                        .build());
-        if(sourceMac != null) {
-            ethernetMatchBuilder.setEthernetSource(new EthernetSourceBuilder()
-                    .setAddress(sourceMac)
-                    .build());
+        LOG.info("in flowManager.addFlow");
+        if(srcMac != null && dstMac.equals(srcMac)) {
+            LOG.info("In addMacToMacFlow: No flows added. Source and Destination MAC are same.");
+            return;
         }
-        EthernetMatch ethernetMatch = ethernetMatchBuilder.build();
-        Match match = new MatchBuilder()
-                .setEthernetMatch(ethernetMatch)
-                .build();
 
+        TableKey flowTableKey = new TableKey(flowTableId);
 
-        Uri destPortUri = destPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+        InstanceIdentifier<Flow> flowPath = buildFlowPath(createMacMatch(srcMac, dstMac), dstNodeConnectorRef, flowTableKey);
+        FlowId flowId = flowPath.firstKeyOf(Flow.class).getId();
 
-        Action outputToControllerAction = new ActionBuilder() //
-                .setOrder(0)
-                .setAction(new OutputActionCaseBuilder() //
-                        .setOutputAction(new OutputActionBuilder() //
-                                .setMaxLength(0xffff) //
-                                .setOutputNodeConnector(destPortUri) //
-                                .build()) //
-                        .build()) //
-                .build();
+        LOG.info("flowPath: " + flowPath.toString());
+        LOG.info("flowId: " + flowId.toString());
 
-        ApplyActions applyActions = new ApplyActionsBuilder().setAction(ImmutableList.of(outputToControllerAction))
-                .build();
+        Flow flowBody = createMacToMacFlow(flowId, flowTableKey.getId(), DEFAULT_PRIORITY, srcMac, dstMac, meterId, dstNodeConnectorRef);
 
-        Instruction applyActionsInstruction = new InstructionBuilder() //
-                .setOrder(0)
-                .setInstruction(new ApplyActionsCaseBuilder()//
-                        .setApplyActions(applyActions) //
-                        .build()) //
-                .build();
+        LOG.info("flowBody: " + flowBody.toString());
 
-        macToMacFlow
-                .setMatch(match) //
-                .setInstructions(new InstructionsBuilder() //
-                        .setInstruction(ImmutableList.of(applyActionsInstruction)) //
-                        .build()) //
-                .setPriority(priority) //
-                .setBufferId(OFP_NO_BUFFER) //
-                .setHardTimeout(flowHardTimeout) //
-                .setIdleTimeout(flowIdleTimeout) //
-                .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
-                .setFlags(new FlowModFlags(false, false, false, false, false));
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+        writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowPath, flowBody, true);
+        try {
+            writeTransaction.submit().checkedGet();
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("Transaction failed: {}", e.toString());
+        }
+        LOG.info("Transaction succeeded");
 
-        return macToMacFlow.build();
     }
 
-    private Flow createIpv4ToIpv4Flow(Short tableId, int priority,
-                                      Ipv4Address sourceIp, Ipv4Address destIp, NodeConnectorRef destPort) {
+    public void writeFlow(Ipv4Address srcIp, Ipv4Address dstIp, NodeConnectorRef dstNodeConnectorRef, Long meterId) {
 
-        FlowBuilder ipToIpFlow = new FlowBuilder() //
-                .setTableId(tableId) //
-                .setFlowName("ip2ip");
+        LOG.info("in flowManager.addFlow");
+        if(srcIp != null && dstIp.equals(srcIp)) {
+            LOG.info("In addIpv4ToIpv4Flow: No flows added. Source and Destination mac are same.");
+            return;
+        }
 
-        ipToIpFlow.setId(new FlowId(Long.toString(ipToIpFlow.hashCode())));
+        TableKey flowTableKey = new TableKey(flowTableId);
 
-        Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder() //
-                    .setIpv4Destination(new Ipv4Prefix(destIp.getValue() + "/32"));
-        if(sourceIp != null) {
-            ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(sourceIp.getValue() + "/32"));
-        }
-        Layer3Match layer3Match = ipv4MatchBuilder.build();
-        Match match = new MatchBuilder()
-                .setLayer3Match(layer3Match)
-                .setEthernetMatch(new EthernetMatchBuilder()
-                        .setEthernetType(new EthernetTypeBuilder()
-                                .setType(new EtherType(0x0800L))
-                                .build())
-                        .build())
-                .build();
+        InstanceIdentifier<Flow> flowPath = buildFlowPath(createIpv4Match(srcIp, dstIp), dstNodeConnectorRef, flowTableKey);
+        FlowId flowId = flowPath.firstKeyOf(Flow.class).getId();
 
+        LOG.info("flowPath: " + flowPath.toString());
+        LOG.info("flowId: " + flowId.toString());
 
-        Uri destPortUri = destPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+        Flow flowBody = createIpv4ToIpv4Flow(flowId, flowTableKey.getId(), DEFAULT_PRIORITY, srcIp, dstIp, meterId, dstNodeConnectorRef);
 
-        Action outputToControllerAction = new ActionBuilder() //
-                .setOrder(0)
-                .setAction(new OutputActionCaseBuilder() //
-                        .setOutputAction(new OutputActionBuilder() //
-                                .setMaxLength(0xffff) //
-                                .setOutputNodeConnector(destPortUri) //
-                                .build()) //
-                        .build()) //
-                .build();
+        LOG.info("flowBody: " + flowBody.toString());
 
-        ApplyActions applyActions = new ApplyActionsBuilder().setAction(ImmutableList.of(outputToControllerAction))
-                .build();
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
 
-        Instruction applyActionsInstruction = new InstructionBuilder() //
-                .setOrder(0)
-                .setInstruction(new ApplyActionsCaseBuilder()//
-                        .setApplyActions(applyActions) //
-                        .build()) //
-                .build();
+        writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowPath, flowBody, true);
+        try {
+            writeTransaction.submit().checkedGet();
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("Transaction failed: {}", e.toString());
+        }
+        LOG.info("Transaction succeed");
 
-        ipToIpFlow
-                .setMatch(match) //
-                .setInstructions(new InstructionsBuilder() //
-                        .setInstruction(ImmutableList.of(applyActionsInstruction)) //
-                        .build()) //
-                .setPriority(priority) //
-                .setBufferId(OFP_NO_BUFFER) //
-                .setHardTimeout(flowHardTimeout) //
-                .setIdleTimeout(flowIdleTimeout) //
-                .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
-                .setFlags(new FlowModFlags(false, false, false, false, false));
+    }
 
-        return ipToIpFlow.build();
+    private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow> getFlowInstanceIdentifier(NodeRef nodeRef, Flow flow) {
+        return ((InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>) nodeRef.getValue())
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(DEFAULT_TABLE_ID))
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow.class,
+                        new FlowKey(new FlowId(flow.getId())));
     }
 
-    private Future<RpcResult<AddFlowOutput>> writeFlowToConfigData(InstanceIdentifier<Flow> flowPath,
-                                                                   Flow flow) {
-        final InstanceIdentifier<Table> tableInstanceId = flowPath.<Table>firstIdentifierOf(Table.class);
-        final InstanceIdentifier<Node> nodeInstanceId = flowPath.<Node>firstIdentifierOf(Node.class);
-        final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
-        builder.setNode(new NodeRef(nodeInstanceId));
-        builder.setFlowRef(new FlowRef(flowPath));
-        builder.setFlowTable(new FlowTableRef(tableInstanceId));
-        builder.setTransactionUri(new Uri(flow.getId().getValue()));
-        return salFlowService.addFlow(builder.build());
+    private InstanceIdentifier<Flow> buildFlowPath(Match match, NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) {
+
+        InstanceIdentifier<Node> nodeIID = InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef);
+        FlowInfoKey flowInfoKey = new FlowInfoKey(nodeIID, match);
+        InstanceIdentifier<Flow> flowPath;
+        if (!this.flowInfo.containsKey(flowInfoKey)) {
+            FlowKey flowKey = new FlowKey(new FlowId(String.valueOf(this.flowIdInc.getAndIncrement())));
+            flowPath = InstanceIdentifierUtils.generateFlowInstanceIdentifier(nodeConnectorRef, flowTableKey, flowKey);
+            this.flowInfo.put(flowInfoKey, flowPath);
+        } else {
+            LOG.info("You should be here");
+            flowPath = this.flowInfo.get(flowInfoKey);
+        }
+
+        return flowPath;
     }
 }
index 7a03e8d77bbf9b1e076574de8576e3297e9ca976..0593c357ecaadcccca7198ceb8e0854c17b5f59c 100644 (file)
@@ -9,6 +9,8 @@
 package org.opendaylight.alto.spce.impl.util;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
@@ -54,4 +56,12 @@ public final class InstanceIdentifierUtils {
                                                                           final FlowKey flowKey) {
         return generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey).child(Flow.class, flowKey);
     }
+
+    public static InstanceIdentifier<Meter> generateMeterInstanceIdentifier(final NodeConnectorRef nodeConnectorRef,
+                                                                            final MeterKey meterKey) {
+        return generateNodeInstanceIdentifier(nodeConnectorRef).builder()
+                .augmentation(FlowCapableNode.class)
+                .child(Meter.class, meterKey)
+                .build();
+    }
 }
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/MeterManager.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/MeterManager.java
new file mode 100644 (file)
index 0000000..166b8ef
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright © 2015 Copyright (c) 2015 SNLAB and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.alto.spce.impl.util;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.endpoints.group.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.BandId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DropBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.MeterBandHeadersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.meter.band.header.MeterBandTypesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+public class MeterManager {
+    private static final Logger LOG = LoggerFactory.getLogger(MeterManager.class);
+    private SalMeterService salMeterService;
+    private DataBroker dataBroker;
+    private final long MIN_METER_ID_PICA8 = 1;
+    private final long MAX_METER_ID_PICA8 = 256;
+    private final String DEFAULT_METER_NAME = "alto-spce rate limiting";
+    private final String DEFAULT_METER_CONTAINER = "alto-spce rate limiting container";
+
+    private HashMap<NodeRef, List<Boolean>> switchToMeterIdListMap = new HashMap<>();
+
+    private HashMap<NodeRef, HashMap<EndpointPairAndRequirement, Long>> switchToPerFlowToMeterIdMap = new HashMap<>();
+
+    public MeterManager(SalMeterService salMeterService, DataBroker dataBroker) {
+        this.salMeterService = salMeterService;
+        this.dataBroker = dataBroker;
+    }
+
+    public void removeMeterFromSwitch (Endpoints endpoint, NodeConnectorRef nodeConnectorRef, long dropRate, long burstSize) {
+        EndpointPairAndRequirement epr = new EndpointPairAndRequirement(endpoint.getSrc().getValue(), endpoint.getDst().getValue(), dropRate, burstSize);
+        NodeRef nodeRef = new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef));
+        int meterId = switchToPerFlowToMeterIdMap.get(nodeRef).get(epr).intValue();
+/*        this.salMeterService.removeMeter(new RemoveMeterInputBuilder()
+                .setMeterId(new MeterId((long)meterId))
+                .setNode(nodeRef)
+                .build());*/
+
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+        writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, buildMeterPath(meterId, nodeConnectorRef));
+        try {
+            writeTransaction.submit().checkedGet();
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("Transaction failed: {}", e.toString());
+        }
+        LOG.info("Transaction succeeded");
+
+        List<Boolean> perSwitchMeterList = switchToMeterIdListMap.get(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)));
+        perSwitchMeterList.set(meterId, false);
+        switchToMeterIdListMap.put(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)), perSwitchMeterList);
+        HashMap<EndpointPairAndRequirement, Long> deleteFlowMeterMap = switchToPerFlowToMeterIdMap.get(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)));
+        deleteFlowMeterMap.remove(epr);
+        switchToPerFlowToMeterIdMap.put(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)), deleteFlowMeterMap);
+    }
+
+    public long addDropMeter(String src, String dst, long dropRate, long dropBurstSize, NodeConnectorRef nodeConnectorRef) {
+        LOG.info("In MeterManager.addDropMeter");
+        List<Boolean> perSwitchMeterList;
+        HashMap<EndpointPairAndRequirement, Long> perSwitchPerFlowToMeterIdMap;
+        if (!switchToMeterIdListMap.containsKey(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)))) {
+            perSwitchMeterList = new LinkedList<>();
+            for (int i=0 ; i<=MAX_METER_ID_PICA8; ++i) {
+                //false stands for meterId == i is free. We must use i from 1 not from 0.
+                perSwitchMeterList.add(false);
+            }
+            switchToMeterIdListMap.put(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)), perSwitchMeterList);
+        }
+        if (!switchToPerFlowToMeterIdMap.containsKey(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)))) {
+            perSwitchPerFlowToMeterIdMap = new HashMap<>();
+            switchToPerFlowToMeterIdMap.put(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)), perSwitchPerFlowToMeterIdMap);
+        }
+
+        perSwitchMeterList = switchToMeterIdListMap.get(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)));
+        perSwitchPerFlowToMeterIdMap = switchToPerFlowToMeterIdMap.get(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)));
+
+        int firstFreeMeterId = 1;
+        while (perSwitchMeterList.get(firstFreeMeterId)) {
+            ++firstFreeMeterId;
+        }
+
+        Meter meter = createDropMeter(dropRate, dropBurstSize, firstFreeMeterId);
+        writeMeterToConfigData(buildMeterPath(firstFreeMeterId, nodeConnectorRef),meter);
+        perSwitchMeterList.set(firstFreeMeterId, true);
+        EndpointPairAndRequirement epr = new EndpointPairAndRequirement(src, dst, dropRate, dropBurstSize);
+        perSwitchPerFlowToMeterIdMap.put(epr, (long)firstFreeMeterId);
+
+        switchToMeterIdListMap.put(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)), perSwitchMeterList);
+        switchToPerFlowToMeterIdMap.put(new NodeRef(InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef)), perSwitchPerFlowToMeterIdMap);
+        return firstFreeMeterId;
+    }
+
+    private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter> buildMeterPath(long meterIdLong, NodeConnectorRef nodeConnectorRef) {
+        MeterId meterId = new MeterId(meterIdLong);
+        MeterKey meterKey = new MeterKey(meterId);
+        return InstanceIdentifierUtils.generateMeterInstanceIdentifier(nodeConnectorRef, meterKey);
+    }
+
+    private Meter createDropMeter(long dropRate, long dropBurstSize, long meterId) {
+        //LOG.info("nodeConnectorRef is" + nodeConnectorRef.toString());
+        DropBuilder dropBuilder = new DropBuilder();
+        dropBuilder
+                .setDropBurstSize(dropBurstSize)
+                .setDropRate(dropRate);
+
+        MeterBandHeaderBuilder mbhBuilder = new MeterBandHeaderBuilder()
+                .setBandType(dropBuilder.build())
+                .setBandId(new BandId(0L))
+                .setMeterBandTypes(new MeterBandTypesBuilder()
+                        .setFlags(new MeterBandType(true, false, false)).build())
+                .setBandRate(dropRate)
+                .setBandBurstSize(dropBurstSize);
+
+        LOG.info("In createDropMeter, MeterBandHeaderBuilder is" + mbhBuilder.toString());
+
+        List<MeterBandHeader> mbhList = new LinkedList<>();
+        mbhList.add(mbhBuilder.build());
+
+        MeterBandHeadersBuilder mbhsBuilder = new MeterBandHeadersBuilder()
+                .setMeterBandHeader(mbhList);
+
+        LOG.info("In createDropMeter, MeterBandHeader is " + mbhBuilder.build().toString());
+        MeterBuilder meterBuilder = new MeterBuilder()
+                .setFlags(new MeterFlags(true, true, false, false))
+                .setMeterBandHeaders(mbhsBuilder.build())
+                .setMeterId(new MeterId(meterId))
+                .setMeterName(DEFAULT_METER_NAME)
+                .setContainerName(DEFAULT_METER_CONTAINER);
+        return meterBuilder.build();
+    }
+
+/*    private Future<RpcResult<AddMeterOutput>> writeMeterToConfigData(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter> meterPath,
+                                                                     Meter meter) {
+        LOG.info("In writeMeterToConfigData");
+        final InstanceIdentifier<Node> nodeInstanceId = meterPath.<Node>firstIdentifierOf(Node.class);
+        final AddMeterInputBuilder builder = new AddMeterInputBuilder(meter);
+        builder.setNode(new NodeRef(nodeInstanceId));
+        builder.setMeterRef(new MeterRef(meterPath));
+        builder.setTransactionUri(new Uri(meter.getMeterId().getValue().toString()));
+        LOG.info("AddMeterInput: " + builder.build());
+        return salMeterService.addMeter(builder.build());
+    }*/
+
+    private void writeMeterToConfigData(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter> meterPath,
+                                                                     Meter meter) {
+
+        org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder mb = new  org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder(meter);
+
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+        writeTransaction.put(LogicalDatastoreType.CONFIGURATION, meterPath, mb.build(), true);
+        try {
+            writeTransaction.submit().checkedGet();
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("Transaction failed: {}", e.toString());
+        }
+        LOG.info("Transaction succeed");
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteInfoKey.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteInfoKey.java
new file mode 100644 (file)
index 0000000..37c7b11
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2015 Copyright (c) 2015 SNLAB and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.alto.spce.impl.util;
+
+public class RouteInfoKey {
+    private String src;
+    private String dst;
+
+    public RouteInfoKey(String src, String dst) {
+        this.src = src;
+        this.dst = dst;
+    }
+
+    public int hashCode() {
+        return this.src.hashCode()+this.dst.hashCode();
+    }
+
+    public boolean equals(Object obj) {
+        if (null == obj) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        RouteInfoKey routeInfoKey = (RouteInfoKey) obj;
+
+        if (null == routeInfoKey.src
+                || null == routeInfoKey.dst
+                || !this.src.equals(routeInfoKey.src)
+                || !this.dst.equals(routeInfoKey.dst)
+                ) {
+            return false;
+        }
+
+        return true;
+    }
+
+
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteInfoValue.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteInfoValue.java
new file mode 100644 (file)
index 0000000..c707281
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2015 Copyright (c) 2015 SNLAB and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.alto.spce.impl.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.FlowType;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+
+import java.util.List;
+
+public class RouteInfoValue {
+    private FlowType flowType;
+    private Long limitedRate;
+    private Long burstSize;
+    private List<TpId> route;
+
+    public RouteInfoValue(FlowType flowType, long limitedRate, long burstSize, List<TpId> route) {
+        this.flowType = flowType;
+        this.limitedRate = limitedRate;
+        this.burstSize = burstSize;
+        this.route = route;
+    }
+
+    public void setFlowType(FlowType flowType) {
+        this.flowType = flowType;
+    }
+
+    public void setLimitedRate(Long limitedRate) {
+        this.limitedRate = new Long(limitedRate);
+    }
+
+    public void setBurstSize(Long burstSize) {
+        this.burstSize = new Long(burstSize);
+    }
+
+    public void setRoute(List<TpId> route) {
+        this.route = route;
+    }
+
+    public FlowType getFlowType() {
+        return this.flowType;
+    }
+
+    public Long getLimitedRate() {
+        return this.limitedRate;
+    }
+
+    public Long getBurstSize() {
+        return this.burstSize;
+    }
+
+    public  List<TpId> getRoute() {
+        return this.route;
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteManager.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/RouteManager.java
new file mode 100644 (file)
index 0000000..b8fc657
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * Copyright © 2015 Copyright (c) 2015 SNLAB and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.alto.spce.impl.util;
+
+import com.google.common.base.Optional;
+import org.opendaylight.alto.spce.impl.algorithm.PathComputation;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.AltoSpceMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.ErrorCodeType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.FlowType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.endpoints.group.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.setup.route.input.ConstraintMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+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.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class RouteManager {
+    private static final Logger LOG = LoggerFactory.getLogger(RouteManager.class);
+
+    private FlowManager flowManager;
+    private MeterManager meterManager;
+    private PathComputation pathComputation;
+    private DataBroker dataBroker;
+    private InventoryReader inventoryReader;
+    private NetworkTrackerService networkTrackerService;
+    private Long NO_METER_SPECIFIED = -1L;
+
+    private HashMap<RouteInfoKey, RouteInfoValue> routeInfo = new HashMap<>();
+
+    public RouteManager(PathComputation pathComputation, InventoryReader inventoryReader
+            , NetworkTrackerService networkTrackerService, FlowManager flowManager, MeterManager meterManager, DataBroker dataBroker) {
+        this.pathComputation = pathComputation;
+        this.inventoryReader = inventoryReader;
+        this.networkTrackerService = networkTrackerService;
+        this.flowManager = flowManager;
+        this.meterManager = meterManager;
+        this.dataBroker = dataBroker;
+    }
+
+    public List<TpId> getRoute(Endpoints endpoints) {
+        RouteInfoKey routeInfoKey = new RouteInfoKey(endpoints.getSrc().getValue(), endpoints.getDst().getValue());
+        RouteInfoValue routeInfoValue = this.routeInfo.get(routeInfoKey);
+        if (null == routeInfoValue) {
+            return null;
+        } else {
+            return routeInfoValue.getRoute();
+        }
+    }
+
+    public List<TpId> computeRoute(Endpoints endpoint,
+                                   List<AltoSpceMetric> altoSpceMetrics,
+                                   List<ConstraintMetric> constraintMetrics) {
+        List<TpId> route = null;
+        TpId srcTpId = getAttachTp(endpoint.getSrc());
+        TpId dstTpId = getAttachTp(endpoint.getDst());
+        Topology topology = getTopology();
+
+        try {
+            if (altoSpceMetrics.get(0) == AltoSpceMetric.Bandwidth) {
+                route = pathComputation.maxBandwidthPath(srcTpId, dstTpId, topology, constraintMetrics);
+            } else if (altoSpceMetrics.get(0) == AltoSpceMetric.Hopcount) {
+                route = pathComputation.shortestPath(srcTpId, dstTpId, topology, constraintMetrics);
+            }
+        } catch (Exception e) {
+            LOG.info("Exception occurs when compute route: " + e.getMessage());
+        }
+        return route;
+    }
+
+    public ErrorCodeType removeRoute(Endpoints endpoints) {
+        RouteInfoKey routeInfoKey = new RouteInfoKey(endpoints.getSrc().getValue(), endpoints.getDst().getValue());
+        RouteInfoValue routeInfoValue = this.routeInfo.get(routeInfoKey);
+        List<TpId> route = routeInfoValue.getRoute();
+        if (route == null) {
+            LOG.info("Remove Route: route is null.");
+            return ErrorCodeType.OK;
+        }
+        try {
+            Ipv4Address srcIp = endpoints.getSrc();
+            Ipv4Address dstIp = endpoints.getDst();
+            MacAddress srcMac = ipToMac(srcIp);
+            MacAddress dstMac = ipToMac(dstIp);
+            for (TpId tpid : route) {
+                String nc_value = tpid.getValue();
+                InstanceIdentifier<NodeConnector> ncid = InstanceIdentifier.builder(Nodes.class)
+                        .child(
+                                Node.class,
+                                new NodeKey(new NodeId(nc_value.substring(0, nc_value.lastIndexOf(':')))))
+                        .child(
+                                NodeConnector.class,
+                                new NodeConnectorKey(new NodeConnectorId(nc_value)))
+                        .build();
+
+                NodeConnectorRef ncr = new NodeConnectorRef(ncid);
+
+                if (routeInfoValue.getFlowType() == FlowType.L3) {
+                    LOG.info("Remove a flow from the switch" + InstanceIdentifierUtils.generateNodeInstanceIdentifier(ncr).firstKeyOf(Node.class).getId().getValue());
+                    this.flowManager.removeFlow(srcIp, dstIp, new NodeConnectorRef(ncid));
+                } else if (routeInfoValue.getFlowType() == FlowType.L2) {
+                    LOG.info("Remove a flow from the switch" + InstanceIdentifierUtils.generateNodeInstanceIdentifier(ncr).firstKeyOf(Node.class).getId().getValue());
+                    this.flowManager.removeFlow(srcMac, dstMac, new NodeConnectorRef(ncid));
+                }
+                if (routeInfoValue.getLimitedRate() > 0 && routeInfoValue.getBurstSize() > 0) {
+                    try {
+                        this.meterManager.removeMeterFromSwitch(endpoints, ncr, routeInfoValue.getLimitedRate(), routeInfoValue.getBurstSize());
+                    } catch (Exception e) {
+                        LOG.info("Exception occurs when remove the meter from " +
+                                InstanceIdentifierUtils.generateNodeInstanceIdentifier(ncr).firstKeyOf(Node.class).getId().getValue());
+                        return ErrorCodeType.REMOVINGMETTERERROR;
+                    }
+                }
+            }
+        } catch (Exception e) {
+            LOG.info("Exception occurs when setup a route: " + e.getMessage());
+            return ErrorCodeType.REMOVINGROUTEERROR;
+        }
+
+        this.routeInfo.remove(routeInfoKey);
+        return ErrorCodeType.OK;
+    }
+
+    public ErrorCodeType removeRateLimiting(Endpoints endpoints) {
+        RouteInfoKey routeInfoKey = new RouteInfoKey(endpoints.getSrc().getValue(), endpoints.getDst().getValue());
+        RouteInfoValue routeInfoValue = this.routeInfo.get(routeInfoKey);
+        List<TpId> route = routeInfoValue.getRoute();
+        if (route == null) {
+            LOG.info("Remove rate limiting error: route is null");
+        } else {
+            if (routeInfoValue.getBurstSize() == -1 && routeInfoValue.getLimitedRate() == -1) {
+                return ErrorCodeType.OK;
+            }
+            try {
+                Ipv4Address srcIp = endpoints.getSrc();
+                Ipv4Address dstIp = endpoints.getDst();
+                MacAddress srcMac = ipToMac(srcIp);
+                MacAddress dstMac = ipToMac(dstIp);
+                FlowType flowLayer = routeInfoValue.getFlowType();
+                if (flowLayer == FlowType.L3) {
+                    LOG.info("Remove the rate limiting: srcIp=" + srcIp.getValue() + ", dstIp=" + dstIp.getValue());
+                } else {
+                    LOG.info("Remove the rate limiting: srcMac=" + srcMac.getValue() + ", dstMac=" + dstMac.getValue());
+                }
+                for (TpId tpid : route) {
+                    String nc_value = tpid.getValue();
+                    InstanceIdentifier<NodeConnector> ncid = InstanceIdentifier.builder(Nodes.class)
+                            .child(
+                                    Node.class,
+                                    new NodeKey(new NodeId(nc_value.substring(0, nc_value.lastIndexOf(':')))))
+                            .child(
+                                    NodeConnector.class,
+                                    new NodeConnectorKey(new NodeConnectorId(nc_value)))
+                            .build();
+
+                    NodeConnectorRef ncr = new NodeConnectorRef(ncid);
+                    try {
+                        this.meterManager.removeMeterFromSwitch(endpoints, ncr, routeInfoValue.getLimitedRate(), routeInfoValue.getBurstSize());
+                    } catch (Exception e) {
+                        LOG.info("Exception occurs when remove the meter from " +
+                                InstanceIdentifierUtils.generateNodeInstanceIdentifier(ncr).firstKeyOf(Node.class).getId().getValue());
+                        return ErrorCodeType.REMOVINGMETTERERROR;
+                    }
+
+                    try {
+                        if (flowLayer == FlowType.L3) {
+                            this.flowManager.writeFlow(srcIp, dstIp, new NodeConnectorRef(ncid), NO_METER_SPECIFIED);
+                        } else if (flowLayer == FlowType.L2) {
+                            this.flowManager.writeFlow(srcMac, dstMac, new NodeConnectorRef(ncid), NO_METER_SPECIFIED);
+                        }
+                    } catch (Exception e) {
+                        LOG.info("Exception occurs when update the flow in " +
+                                InstanceIdentifierUtils.generateNodeInstanceIdentifier(ncr).firstKeyOf(Node.class).getId().getValue());
+                        return ErrorCodeType.SETTINGUPROUTEERROR;
+                    }
+                }
+            } catch (Exception e) {
+                LOG.info("Exception occurs when remove a rate limiting: " + e.getMessage());
+                return ErrorCodeType.SETTINGUPROUTEERROR;
+            }
+            RouteInfoValue routeInfoValueNew = new RouteInfoValue(routeInfoValue.getFlowType(), -1L, -1L, route);
+            this.routeInfo.put(routeInfoKey, routeInfoValueNew);
+            return ErrorCodeType.OK;
+        }
+        return ErrorCodeType.UNDEFINEDERROR;
+    }
+
+    public ErrorCodeType updateRateLimiting(Endpoints endpoints, long limitedRate, long burstSize) {
+        RouteInfoKey routeInfoKey = new RouteInfoKey(endpoints.getSrc().getValue(), endpoints.getDst().getValue());
+        RouteInfoValue routeInfoValue = this.routeInfo.get(routeInfoKey);
+        if (routeInfoValue == null) {
+            LOG.info("Update rate limiting error: route is null");
+            return ErrorCodeType.MISSINGROUTEERROR;
+        }
+        List<TpId> route = routeInfoValue.getRoute();
+        if (route == null) {
+            LOG.info("Update rate limiting error: route is null");
+            return ErrorCodeType.MISSINGROUTEERROR;
+        } else {
+            try {
+                Ipv4Address srcIp = endpoints.getSrc();
+                Ipv4Address dstIp = endpoints.getDst();
+                MacAddress srcMac = ipToMac(srcIp);
+                MacAddress dstMac = ipToMac(dstIp);
+                FlowType flowLayer = routeInfoValue.getFlowType();
+                if (flowLayer == FlowType.L3) {
+                    LOG.info("Update the rate limiting: srcIp=" + srcIp.getValue() + ", dstIp=" + dstIp.getValue() + ", limitedRate=" + limitedRate + ", burstSize=" + burstSize);
+                } else {
+                    LOG.info("Update the rate limiting: srcMac=" + srcMac.getValue() + ", dstMac=" + dstMac.getValue() + ", limitedRate=" + limitedRate + ", burstSize=" + burstSize);
+                }
+                for (TpId tpid : route) {
+                    String nc_value = tpid.getValue();
+                    InstanceIdentifier<NodeConnector> ncid = InstanceIdentifier.builder(Nodes.class)
+                            .child(
+                                    Node.class,
+                                    new NodeKey(new NodeId(nc_value.substring(0, nc_value.lastIndexOf(':')))))
+                            .child(
+                                    NodeConnector.class,
+                                    new NodeConnectorKey(new NodeConnectorId(nc_value)))
+                            .build();
+                    NodeConnectorRef ncr = new NodeConnectorRef(ncid);
+                    if (routeInfoValue.getLimitedRate() > 0 && routeInfoValue.getBurstSize() > 0) {
+                        try {
+                            this.meterManager.removeMeterFromSwitch(endpoints, ncr, routeInfoValue.getLimitedRate(), routeInfoValue.getBurstSize());
+                        } catch (Exception e) {
+                            LOG.info("Exception occurs when remove the meter from " +
+                                    InstanceIdentifierUtils.generateNodeInstanceIdentifier(ncr).firstKeyOf(Node.class).getId().getValue());
+                            return ErrorCodeType.REMOVINGMETTERERROR;
+                        }
+                    }
+
+                    long meterId = NO_METER_SPECIFIED;
+                    if (limitedRate > 0 && burstSize > 0) {
+                        try {
+                            meterId = this.meterManager.addDropMeter(srcIp.getValue(), dstIp.getValue(), limitedRate, burstSize, ncr);
+                        } catch (Exception e) {
+                            LOG.info("Exception occurs when add the meter to " +
+                                    InstanceIdentifierUtils.generateNodeInstanceIdentifier(ncr).firstKeyOf(Node.class).getId().getValue());
+                            return ErrorCodeType.SETTINGUPMETERERROR;
+                        }
+                    }
+
+                    try {
+                        if (flowLayer == FlowType.L3) {
+                            this.flowManager.writeFlow(srcIp, dstIp, new NodeConnectorRef(ncid), meterId);
+                        } else if (flowLayer == FlowType.L2) {
+                            this.flowManager.writeFlow(srcMac, dstMac, new NodeConnectorRef(ncid), meterId);
+                        }
+                    } catch (Exception e) {
+                        LOG.info("Exception occurs when update the flow in " +
+                                InstanceIdentifierUtils.generateNodeInstanceIdentifier(ncr).firstKeyOf(Node.class).getId().getValue());
+                        return ErrorCodeType.SETTINGUPROUTEERROR;
+                    }
+                }
+            } catch (Exception e) {
+                LOG.info("Exception occurs when update a rate limiting: " + e.getMessage());
+                return ErrorCodeType.UPDATINGRATELIMITINGERROR;
+            }
+            RouteInfoValue routeInfoValueNew = new RouteInfoValue(routeInfoValue.getFlowType(), limitedRate, burstSize, route);
+            this.routeInfo.put(routeInfoKey, routeInfoValueNew);
+            return ErrorCodeType.OK;
+        }
+    }
+
+
+    public ErrorCodeType setupRoute(Endpoints endpoints, List<TpId> route, FlowType flowLayer, long limitedRate, long burstSize) {
+        Ipv4Address srcIp = endpoints.getSrc();
+        Ipv4Address dstIp = endpoints.getDst();
+        RouteInfoKey routeInfoKey = new RouteInfoKey(srcIp.getValue(), dstIp.getValue());
+        RouteInfoValue routeInfoValue = this.routeInfo.get(routeInfoKey);
+        if (routeInfoValue!= null) {
+            ErrorCodeType errorCodeType = removeRoute(endpoints);
+            if (errorCodeType!= ErrorCodeType.OK) {
+                return errorCodeType;
+            }
+        }
+
+        if (route == null) {
+            LOG.info("Set up the route error: route is null.");
+            return ErrorCodeType.COMPUTINGROUTEERROR;
+        }
+
+        try {
+            MacAddress srcMac = ipToMac(srcIp);
+            MacAddress dstMac = ipToMac(dstIp);
+            if (flowLayer == FlowType.L3) {
+                LOG.info("Set up a route: srcIp=" + srcIp.getValue() + ", dstIp=" + dstIp.getValue() + ", limitedRate=" + limitedRate + ", burstSize=" + burstSize);
+            } else {
+                LOG.info("Set up a route: srcMac=" + srcMac.getValue() + ", dstMac=" + dstMac.getValue() + ", limitedRate=" + limitedRate + ", burstSize=" + burstSize);
+            }
+            for (TpId tpid : route) {
+                String nc_value = tpid.getValue();
+                InstanceIdentifier<NodeConnector> ncid = InstanceIdentifier.builder(Nodes.class)
+                        .child(
+                                Node.class,
+                                new NodeKey(new NodeId(nc_value.substring(0, nc_value.lastIndexOf(':')))))
+                        .child(
+                                NodeConnector.class,
+                                new NodeConnectorKey(new NodeConnectorId(nc_value)))
+                        .build();
+                long meterId = NO_METER_SPECIFIED;
+                if (limitedRate > 0 && burstSize > 0) {
+                    try {
+                        meterId = this.meterManager.addDropMeter(srcIp.getValue(), dstIp.getValue(), limitedRate, burstSize, new NodeConnectorRef(ncid));
+                    } catch (Exception e) {
+                        LOG.info("Exception occurs when set up a meter: " + e.getMessage());
+                        return ErrorCodeType.SETTINGUPMETERERROR;
+                    }
+                }
+                if (flowLayer == FlowType.L3) {
+                    this.flowManager.writeFlow(srcIp, dstIp, new NodeConnectorRef(ncid), meterId);
+                } else if (flowLayer == FlowType.L2) {
+                    this.flowManager.writeFlow(srcMac, dstMac, new NodeConnectorRef(ncid), meterId);
+                }
+
+            }
+        } catch (Exception e) {
+            LOG.info("Exception occurs when set up a route: " + e.getMessage());
+            return ErrorCodeType.SETTINGUPROUTEERROR;
+        }
+
+        routeInfoValue = new RouteInfoValue(flowLayer, limitedRate, burstSize, route);
+        this.routeInfo.put(routeInfoKey, routeInfoValue);
+        return ErrorCodeType.OK;
+    }
+
+    private TpId getAttachTp(Ipv4Address src) {
+        return this.inventoryReader.getNodeConnectorByMac(ipToMac(src));
+    }
+
+    private MacAddress ipToMac(Ipv4Address src) {
+        MacAddress mac = null;
+        AltoSpceGetMacByIpInput input = new AltoSpceGetMacByIpInputBuilder()
+                .setIpAddress(src.getValue())
+                .build();
+        Future<RpcResult<AltoSpceGetMacByIpOutput>> result = this.networkTrackerService.altoSpceGetMacByIp(input);
+        try {
+            AltoSpceGetMacByIpOutput output = result.get().getResult();
+            mac = new MacAddress(output.getMacAddress());
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.info("Exception occurs when convert ip to mac: " + e.getMessage());
+        }
+        return mac;
+    }
+
+    private Topology getTopology() {
+        try {
+            ReadOnlyTransaction readTx = this.dataBroker.newReadOnlyTransaction();
+
+            InstanceIdentifier<Topology> topologyInstanceIdentifier = InstanceIdentifier
+                    .builder(NetworkTopology.class)
+                    .child(Topology.class, new TopologyKey(new TopologyId("flow:1")))
+                    .build();
+
+            Optional<Topology> dataFuture = readTx.read(LogicalDatastoreType.OPERATIONAL,
+                    topologyInstanceIdentifier).get();
+
+            return dataFuture.get();
+        } catch (Exception e) {
+            LOG.info("Exception occurs when get topology: " + e.getMessage());
+        }
+        return null;
+    }
+}
index c89e5bf90d662ef7cf01027861a6a311ad16fabb..8577c4392f864985fde9b177002a5691e67702f8 100644 (file)
@@ -22,11 +22,44 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
   <prerequisites>
     <maven>3.1.1</maven>
   </prerequisites>
-  <modules>
-    <module>network-tracker</module>
-    <module>api</module>
-    <module>impl</module>
-  </modules>
+
+  <profiles>
+    <profile>
+      <id>minimal</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+      <modules>
+        <module>network-tracker</module>
+        <module>api</module>
+        <module>impl</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>alto-dev</id>
+      <modules>
+        <module>network-tracker</module>
+        <module>api</module>
+        <module>impl</module>
+        <module>features</module>
+        <module>artifacts</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>alto-test</id>
+      <modules>
+        <module>network-tracker</module>
+        <module>api</module>
+        <module>impl</module>
+        <module>features</module>
+        <module>artifacts</module>
+        <module>karaf</module>
+      </modules>
+    </profile>
+  </profiles>
+
   <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
   <build>
     <plugins>
index 6a158f7ca9fd5a7d62d406ded5760552bb9b95d2..5891bbf76976905a589db57b23d9f3b8a4d792ff 100644 (file)
@@ -60,9 +60,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <feature version="${l2switch.version}">odl-l2switch-switch</feature>
     <!-- odl-l2switch-arphandler uses blueprint now, but we still attempt to write data to
     the config subsystem in order to set is-proactive-flood-mode to false. -->
-    <configfile finalname="${configfile.directory}/54-alto-arphandler.xml">
-      mvn:org.opendaylight.alto.spce.network/network-tracker-config/${project.version}/xml/config
-    </configfile>
 
     <bundle>mvn:org.opendaylight.alto.spce.network/network-tracker-api/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.alto.spce.network/network-tracker-impl/${project.version}</bundle>