+/*
+ * 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;
<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>
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;
}
}
}
}
- 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;
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;
}
}
}
}
}
+
+ 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;
+ }
+
+ }
+ }
+
}
<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>
<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>
<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'>
<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>
<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>
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;
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) {
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();
}
}
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;
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
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;
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
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;
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;
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;
}
}
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;
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();
+ }
}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
<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>
<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>