Marc De Leenheer
Committed by Gerrit Code Review

Rewrote optical connectivity intent compiler

Change-Id: I5acece3c14bed8a23f7bbe0c5a9bc0932a2a0881
Showing 21 changed files with 625 additions and 118 deletions
......@@ -45,7 +45,6 @@
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
......@@ -59,6 +58,12 @@
<artifactId>jackson-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-serializers</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
......
......@@ -26,7 +26,7 @@ public interface Device extends Element {
* Coarse classification of the type of the infrastructure device.
*/
public enum Type {
SWITCH, ROUTER, ROADM, OTN, FIREWALL, BALANCER, IPS, IDS, CONTROLLER, OTHER
SWITCH, ROUTER, ROADM, OTN, ROADM_OTN, FIREWALL, BALANCER, IPS, IDS, CONTROLLER, OTHER
}
/**
......
......@@ -15,8 +15,6 @@
*/
package org.onosproject.net;
import org.onlab.util.Frequency;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
......@@ -29,9 +27,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class OchPort extends DefaultPort {
public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5);
private final OduSignalType signalType;
private final boolean isTunable;
private final OchSignal lambda;
......@@ -43,7 +38,7 @@ public class OchPort extends DefaultPort {
* @param number port number
* @param isEnabled port enabled state
* @param signalType ODU signal type
* @param isTunable maximum frequency in MHz
* @param isTunable tunable wavelength capability
* @param lambda OCh signal
* @param annotations optional key/value annotations
*/
......
......@@ -30,11 +30,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
* See ITU G.709 "Interfaces for the Optical Transport Network (OTN)".
* </p>
*/
// TODO: consider which is better, OchSignal or OpticalChannelSignal
public class OchSignal implements Lambda {
private static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
private static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5);
public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5);
private final GridType gridType;
private final ChannelSpacing channelSpacing;
......@@ -57,10 +56,9 @@ public class OchSignal implements Lambda {
int spacingMultiplier, int slotGranularity) {
this.gridType = checkNotNull(gridType);
this.channelSpacing = checkNotNull(channelSpacing);
// TODO: check the precondition for spacingMultiplier. Is negative value permitted?
// Negative values are permitted for spacingMultiplier
this.spacingMultiplier = spacingMultiplier;
checkArgument(slotGranularity > 0, "slotGranularity must be more than 0, but %s", slotGranularity);
checkArgument(slotGranularity > 0, "slotGranularity must be larger than 0, received %s", slotGranularity);
this.slotGranularity = slotGranularity;
}
......
......@@ -40,7 +40,7 @@ public class OchPortDescription extends DefaultPortDescription {
* @param isEnabled port enabled state
* @param signalType ODU signal type
* @param isTunable tunable wavelength capability
* @param lambda Och signal
* @param lambda OCh signal
* @param annotations optional key/value annotations map
*/
public OchPortDescription(PortNumber number, boolean isEnabled, OduSignalType signalType,
......
......@@ -24,8 +24,8 @@ import java.util.Collections;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* An optical layer intent for connectivity from one transponder port to another
* transponder port. No traffic selector or traffic treatment are needed.
* An optical layer intent for connectivity between two OCh ports.
* No traffic selector or traffic treatment are needed.
*/
public final class OpticalConnectivityIntent extends Intent {
private final ConnectPoint src;
......
......@@ -15,11 +15,9 @@
*/
package org.onosproject.net.intent;
import java.util.Collection;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Link;
import org.onosproject.net.OchSignal;
import org.onosproject.net.Path;
import com.google.common.base.MoreObjects;
......@@ -32,27 +30,27 @@ public final class OpticalPathIntent extends Intent {
private final ConnectPoint src;
private final ConnectPoint dst;
private final Path path;
private final OchSignal lambda;
private OpticalPathIntent(ApplicationId appId,
Key key,
ConnectPoint src,
ConnectPoint dst,
Path path,
OchSignal lambda,
int priority) {
super(appId,
key,
ImmutableSet.copyOf(path.links()),
priority);
super(appId, key, ImmutableSet.copyOf(path.links()), priority);
this.src = checkNotNull(src);
this.dst = checkNotNull(dst);
this.path = checkNotNull(path);
this.lambda = checkNotNull(lambda);
}
protected OpticalPathIntent() {
this.src = null;
this.dst = null;
this.path = null;
this.lambda = null;
}
/**
......@@ -72,6 +70,7 @@ public final class OpticalPathIntent extends Intent {
private ConnectPoint src;
private ConnectPoint dst;
private Path path;
private OchSignal lambda;
Key key;
@Override
......@@ -123,6 +122,17 @@ public final class OpticalPathIntent extends Intent {
}
/**
* Sets the optical channel (lambda) for the intent that will be built.
*
* @param lambda the optical channel
* @return this builder
*/
public Builder lambda(OchSignal lambda) {
this.lambda = lambda;
return this;
}
/**
* Builds an optical path intent from the accumulated parameters.
*
* @return optical path intent
......@@ -135,6 +145,7 @@ public final class OpticalPathIntent extends Intent {
src,
dst,
path,
lambda,
priority
);
}
......@@ -153,6 +164,10 @@ public final class OpticalPathIntent extends Intent {
return path;
}
public OchSignal lambda() {
return lambda;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
......@@ -163,11 +178,7 @@ public final class OpticalPathIntent extends Intent {
.add("ingressPort", src)
.add("egressPort", dst)
.add("path", path)
.add("lambda", lambda)
.toString();
}
public Collection<Link> requiredLinks() {
return path.links();
}
}
......
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.resource;
import org.onosproject.net.Port;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentId;
import java.util.Set;
/**
* Service for providing device resources.
*/
public interface DeviceResourceService {
/**
* Request a set of ports needed to satisfy the intent.
*
* @param intent the intent
* @return set of ports
*/
Set<Port> requestPorts(Intent intent);
/**
* Release ports associated with given intent ID.
*
* @param intentId intent ID
*/
void releasePorts(IntentId intentId);
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.resource;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.intent.IntentId;
import java.util.Set;
public interface DeviceResourceStore {
Set<Port> getFreePorts(DeviceId deviceId);
void allocatePorts(Set<Port> port, IntentId intent);
void releasePorts(IntentId intent);
}
......@@ -89,6 +89,10 @@ public final class NetTestTools {
return new DefaultPath(PID, links, ids.length);
}
// Creates OCh signal
public static OchSignal createLambda() {
return new OchSignal(GridType.DWDM, ChannelSpacing.CHL_6P25GHZ, 8, 4);
}
/**
* Verifies that Annotations created by merging {@code annotations} is
......
......@@ -18,6 +18,7 @@ package org.onosproject.net.intent;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.net.OchSignal;
import org.onosproject.net.Path;
import com.google.common.testing.EqualsTester;
......@@ -28,6 +29,7 @@ import static org.hamcrest.core.IsEqual.equalTo;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.connectPoint;
import static org.onosproject.net.NetTestTools.createLambda;
import static org.onosproject.net.NetTestTools.createPath;
public class OpticalPathIntentTest extends AbstractIntentTest {
......@@ -37,6 +39,7 @@ public class OpticalPathIntentTest extends AbstractIntentTest {
OpticalPathIntent intent1;
OpticalPathIntent intent2;
Path defaultPath;
OchSignal lambda;
@Before
public void opticalPathIntentTestSetUp() {
......@@ -46,6 +49,7 @@ public class OpticalPathIntentTest extends AbstractIntentTest {
.src(connectPoint("one", 1))
.dst(connectPoint("two", 2))
.path(defaultPath)
.lambda(createLambda())
.priority(PRIORITY)
.build();
......@@ -54,6 +58,7 @@ public class OpticalPathIntentTest extends AbstractIntentTest {
.src(connectPoint("two", 1))
.dst(connectPoint("one", 2))
.path(defaultPath)
.lambda(createLambda())
.priority(PRIORITY)
.build();
}
......
......@@ -15,6 +15,7 @@
*/
package org.onosproject.net.intent.impl.compiler;
import java.util.Collections;
import java.util.List;
import java.util.Set;
......@@ -23,16 +24,31 @@ import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.util.Frequency;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.GridType;
import org.onosproject.net.Link;
import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OmsPort;
import org.onosproject.net.Path;
import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.OpticalPathIntent;
import org.onosproject.net.intent.impl.PathNotFoundException;
import org.onosproject.net.resource.DefaultLinkResourceRequest;
import org.onosproject.net.resource.DeviceResourceService;
import org.onosproject.net.resource.LambdaResource;
import org.onosproject.net.resource.LambdaResourceAllocation;
import org.onosproject.net.resource.LinkResourceAllocations;
import org.onosproject.net.resource.LinkResourceRequest;
import org.onosproject.net.resource.LinkResourceService;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceType;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyEdge;
......@@ -40,18 +56,32 @@ import org.onosproject.net.topology.TopologyService;
import com.google.common.collect.ImmutableList;
import static com.google.common.base.Preconditions.checkArgument;
/**
* An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
*/
@Component(immediate = true)
public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM;
private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentExtensionService intentManager;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkResourceService linkResourceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceResourceService deviceResourceService;
@Activate
public void activate() {
intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
......@@ -66,19 +96,152 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
public List<Intent> compile(OpticalConnectivityIntent intent,
List<Intent> installable,
Set<LinkResourceAllocations> resources) {
// TODO: compute multiple paths using the K-shortest path algorithm
Path path = calculateOpticalPath(intent.getSrc(), intent.getDst());
Intent newIntent = OpticalPathIntent.builder()
.appId(intent.appId())
.src(intent.getSrc())
.dst(intent.getDst())
.path(path)
.build();
return ImmutableList.of(newIntent);
// Check if source and destination are optical OCh ports
ConnectPoint src = intent.getSrc();
ConnectPoint dst = intent.getDst();
Port srcPort = deviceService.getPort(src.deviceId(), src.port());
Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
checkArgument(srcPort instanceof OchPort);
checkArgument(dstPort instanceof OchPort);
// Calculate available light paths
Set<Path> paths = getOpticalPaths(intent);
// Use first path that can be successfully reserved
for (Path path : paths) {
// Request and reserve lambda on path
LinkResourceAllocations linkAllocs = assignWavelength(intent, path);
if (linkAllocs == null) {
continue;
}
OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port());
// Try to reserve port resources, roll back if unsuccessful
Set<Port> portAllocs = deviceResourceService.requestPorts(intent);
if (portAllocs == null) {
linkResourceService.releaseResources(linkAllocs);
continue;
}
// Create installable optical path intent
LambdaResourceAllocation lambdaAlloc = getWavelength(path, linkAllocs);
OchSignal ochSignal = getOchSignal(lambdaAlloc, omsPort.minFrequency(), omsPort.grid());
Intent newIntent = OpticalPathIntent.builder()
.appId(intent.appId())
.src(intent.getSrc())
.dst(intent.getDst())
.path(path)
.lambda(ochSignal)
.build();
return ImmutableList.of(newIntent);
}
return Collections.emptyList();
}
/**
* Find the lambda allocated to the path.
*
* @param path the path
* @param linkAllocs the link allocations
* @return
*/
private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) {
for (Link link : path.links()) {
for (ResourceAllocation alloc : linkAllocs.getResourceAllocation(link)) {
if (alloc.type() == ResourceType.LAMBDA) {
return (LambdaResourceAllocation) alloc;
}
}
}
return null;
}
/**
* Request and reserve first available wavelength across path.
*
* @param path path in WDM topology
* @return first available lambda resource allocation
*/
private LinkResourceAllocations assignWavelength(Intent intent, Path path) {
LinkResourceRequest.Builder request =
DefaultLinkResourceRequest.builder(intent.id(), path.links())
.addLambdaRequest();
LinkResourceAllocations allocations = linkResourceService.requestResources(request.build());
checkWavelengthContinuity(allocations, path);
return allocations;
}
/**
* Checks wavelength continuity constraint across path, i.e., an identical lambda is used on all links.
* @return true if wavelength continuity is met, false otherwise
*/
private boolean checkWavelengthContinuity(LinkResourceAllocations allocations, Path path) {
if (allocations == null) {
return false;
}
LambdaResource lambda = null;
for (Link link : path.links()) {
for (ResourceAllocation alloc : allocations.getResourceAllocation(link)) {
if (alloc.type() == ResourceType.LAMBDA) {
LambdaResource nextLambda = ((LambdaResourceAllocation) alloc).lambda();
if (nextLambda == null) {
return false;
}
if (lambda == null) {
lambda = nextLambda;
continue;
}
if (!lambda.equals(nextLambda)) {
return false;
}
}
}
}
return true;
}
/**
* Convert lambda resource allocation in OCh signal.
*
* @param alloc lambda resource allocation
* @param minFrequency minimum frequency
* @param grid grid spacing frequency
* @return OCh signal
*/
private OchSignal getOchSignal(LambdaResourceAllocation alloc, Frequency minFrequency, Frequency grid) {
int channel = alloc.lambda().toInt();
// Calculate center frequency
Frequency centerFrequency = minFrequency.add(grid.multiply(channel)).add(grid.floorDivision(2));
// Build OCh signal object
int spacingMultiplier = (int) (centerFrequency.subtract(OchSignal.CENTER_FREQUENCY).asHz() / grid.asHz());
int slotGranularity = (int) (grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
OchSignal ochSignal = new OchSignal(DEFAULT_OCH_GRIDTYPE, DEFAULT_CHANNEL_SPACING,
spacingMultiplier, slotGranularity);
return ochSignal;
}
private Path calculateOpticalPath(ConnectPoint start, ConnectPoint end) {
// TODO: support user policies
/**
* Calculates optical paths in WDM topology.
*
* @param intent optical connectivity intent
* @return set of paths in WDM topology
*/
private Set<Path> getOpticalPaths(OpticalConnectivityIntent intent) {
// Route in WDM topology
Topology topology = topologyService.currentTopology();
LinkWeight weight = new LinkWeight() {
@Override
......@@ -86,18 +249,18 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
if (edge.link().state() == Link.State.INACTIVE) {
return -1;
}
return edge.link().type() == Link.Type.OPTICAL ? +1 : -1;
if (edge.link().type() != Link.Type.OPTICAL) {
return -1;
}
return edge.link().annotations().value("optical.type").equals("WDM") ? +1 : -1;
}
};
ConnectPoint start = intent.getSrc();
ConnectPoint end = intent.getDst();
Set<Path> paths = topologyService.getPaths(topology, start.deviceId(),
end.deviceId(), weight);
if (paths.isEmpty()) {
throw new PathNotFoundException(start.elementId(), end.elementId());
}
end.deviceId(), weight);
// TODO: let's be more intelligent about this eventually
return paths.iterator().next();
return paths;
}
}
......
......@@ -30,29 +30,21 @@ import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.OpticalPathIntent;
import org.onosproject.net.intent.impl.IntentCompilationException;
import org.onosproject.net.resource.DefaultLinkResourceRequest;
import org.onosproject.net.resource.LambdaResource;
import org.onosproject.net.resource.LambdaResourceAllocation;
import org.onosproject.net.resource.LinkResourceAllocations;
import org.onosproject.net.resource.LinkResourceRequest;
import org.onosproject.net.resource.LinkResourceService;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceType;
import org.onosproject.net.topology.TopologyService;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;
@Component(immediate = true)
public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathIntent> {
......@@ -63,15 +55,10 @@ public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathInte
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkResourceService resourceService;
private ApplicationId appId;
static final short SIGNAL_TYPE = (short) 1;
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.net.intent");
......@@ -86,64 +73,50 @@ public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathInte
@Override
public List<Intent> compile(OpticalPathIntent intent, List<Intent> installable,
Set<LinkResourceAllocations> resources) {
LinkResourceAllocations allocations = assignWavelength(intent);
return Collections.singletonList(
new FlowRuleIntent(appId, createRules(intent, allocations), intent.resources()));
new FlowRuleIntent(appId, createRules(intent), intent.resources()));
}
private LinkResourceAllocations assignWavelength(OpticalPathIntent intent) {
LinkResourceRequest.Builder request = DefaultLinkResourceRequest
.builder(intent.id(), intent.path().links())
.addLambdaRequest();
return resourceService.requestResources(request.build());
}
private List<FlowRule> createRules(OpticalPathIntent intent, LinkResourceAllocations allocations) {
private List<FlowRule> createRules(OpticalPathIntent intent) {
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchInPort(intent.src().port());
List<FlowRule> rules = new LinkedList<>();
ConnectPoint prev = intent.src();
ConnectPoint current = intent.src();
for (Link link : intent.path().links()) {
ResourceAllocation allocation = allocations.getResourceAllocation(link).stream()
.filter(x -> x.type() == ResourceType.LAMBDA)
.findFirst()
.orElseThrow(() -> new IntentCompilationException("Lambda was not assigned successfully"));
LambdaResource la = ((LambdaResourceAllocation) allocation).lambda();
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
treatmentBuilder.setLambda((short) la.toInt());
treatmentBuilder.add(Instructions.modL0Lambda(intent.lambda()));
treatmentBuilder.setOutput(link.src().port());
FlowRule rule = new DefaultFlowRule(prev.deviceId(),
selectorBuilder.build(),
treatmentBuilder.build(),
100,
appId,
100,
true);
FlowRule rule = DefaultFlowRule.builder()
.forDevice(current.deviceId())
.withSelector(selectorBuilder.build())
.withTreatment(treatmentBuilder.build())
.withPriority(100)
.fromApp(appId)
.makePermanent()
.build();
rules.add(rule);
prev = link.dst();
current = link.dst();
selectorBuilder.matchInPort(link.dst().port());
selectorBuilder.matchOpticalSignalType(SIGNAL_TYPE);
selectorBuilder.matchLambda((short) la.toInt());
selectorBuilder.add(Criteria.matchLambda(intent.lambda()));
}
// build the last T port rule
TrafficTreatment.Builder treatmentLast = builder();
// Build the egress ROADM rule
TrafficTreatment.Builder treatmentLast = DefaultTrafficTreatment.builder();
treatmentLast.setOutput(intent.dst().port());
FlowRule rule = new DefaultFlowRule(intent.dst().deviceId(),
selectorBuilder.build(),
treatmentLast.build(),
100,
appId,
100,
true);
FlowRule rule = new DefaultFlowRule.Builder()
.forDevice(intent.dst().deviceId())
.withSelector(selectorBuilder.build())
.withTreatment(treatmentLast.build())
.withPriority(100)
.fromApp(appId)
.makePermanent()
.build();
rules.add(rule);
return rules;
......
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.resource.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.net.Port;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.resource.DeviceResourceService;
import org.onosproject.net.resource.DeviceResourceStore;
import org.slf4j.Logger;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Provides basic implementation of device resources allocation.
*/
@Component(immediate = true)
@Service
public class DeviceResourceManager implements DeviceResourceService {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private DeviceResourceStore store;
@Activate
public void activate() {
log.info("Started");
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
@Override
public Set<Port> requestPorts(Intent intent) {
checkNotNull(intent);
if (intent instanceof OpticalConnectivityIntent) {
OpticalConnectivityIntent opticalIntent = (OpticalConnectivityIntent) intent;
Set<Port> srcPorts = store.getFreePorts(opticalIntent.getSrc().deviceId());
Set<Port> dstPorts = store.getFreePorts(opticalIntent.getDst().deviceId());
Port srcPort = getTypedPort(srcPorts, Port.Type.OCH);
Port dstPort = getTypedPort(dstPorts, Port.Type.OCH);
if (srcPort == null || dstPort == null) {
return null;
}
Set<Port> allocPorts = new HashSet(Arrays.asList(srcPort, dstPort));
store.allocatePorts(allocPorts, intent.id());
return allocPorts;
}
return null;
}
@Override
public void releasePorts(IntentId intentId) {
store.releasePorts(intentId);
}
private Port getTypedPort(Set<Port> ports, Port.Type type) {
for (Port port : ports) {
if (port.type() == type) {
return port;
}
}
return null;
}
}
......@@ -52,6 +52,7 @@ import static org.hamcrest.Matchers.hasSize;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.NetTestTools.PID;
import static org.onosproject.net.NetTestTools.connectPoint;
import static org.onosproject.net.NetTestTools.createLambda;
public class OpticalPathIntentCompilerTest {
......@@ -93,6 +94,7 @@ public class OpticalPathIntentCompilerTest {
.src(d1p1)
.dst(d3p1)
.path(new DefaultPath(PID, links, hops))
.lambda(createLambda())
.build();
intentExtensionService = createMock(IntentExtensionService.class);
intentExtensionService.registerCompiler(OpticalPathIntent.class, sut);
......
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.resource.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.KryoNamespace;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.resource.DeviceResourceStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.TransactionContext;
import org.onosproject.store.service.TransactionalMap;
import org.slf4j.Logger;
import java.util.HashSet;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static org.slf4j.LoggerFactory.getLogger;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Store that manages device resources using Copycat-backed TransactionalMaps.
*/
@Component(immediate = true, enabled = true)
@Service
public class ConsistentDeviceResourceStore implements DeviceResourceStore {
private final Logger log = getLogger(getClass());
private static final String PORT_ALLOCATIONS = "PortAllocations";
private static final String INTENT_ALLOCATIONS = "IntentAllocations";
private static final Serializer SERIALIZER = Serializer.using(
new KryoNamespace.Builder().register(KryoNamespaces.API).build());
private ConsistentMap<Port, IntentId> portAllocMap;
private ConsistentMap<IntentId, Set<Port>> intentAllocMap;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Activate
public void activate() {
portAllocMap = storageService.<Port, IntentId>consistentMapBuilder()
.withName(PORT_ALLOCATIONS)
.withSerializer(SERIALIZER)
.build();
intentAllocMap = storageService.<IntentId, Set<Port>>consistentMapBuilder()
.withName(INTENT_ALLOCATIONS)
.withSerializer(SERIALIZER)
.build();
log.info("Started");
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
private TransactionalMap<Port, IntentId> getPortAllocs(TransactionContext tx) {
return tx.getTransactionalMap(PORT_ALLOCATIONS, SERIALIZER);
}
private TransactionalMap<IntentId, Set<Port>> getIntentAllocs(TransactionContext tx) {
return tx.getTransactionalMap(INTENT_ALLOCATIONS, SERIALIZER);
}
private TransactionContext getTxContext() {
return storageService.transactionContextBuilder().build();
}
@Override
public Set<Port> getFreePorts(DeviceId deviceId) {
checkNotNull(deviceId);
Set<Port> freePorts = new HashSet<>();
for (Port port : deviceService.getPorts(deviceId)) {
if (!portAllocMap.containsKey(port)) {
freePorts.add(port);
}
}
return freePorts;
}
@Override
public void allocatePorts(Set<Port> ports, IntentId intentId) {
checkNotNull(ports);
checkArgument(ports.size() > 0);
checkNotNull(intentId);
TransactionContext tx = getTxContext();
tx.begin();
try {
TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
for (Port port : ports) {
portAllocs.put(port, intentId);
}
TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
intentAllocs.put(intentId, ports);
tx.commit();
} catch (Exception e) {
log.error("Exception thrown, rolling back", e);
tx.abort();
throw e;
}
}
@Override
public void releasePorts(IntentId intentId) {
checkNotNull(intentId);
TransactionContext tx = getTxContext();
tx.begin();
try {
TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
Set<Port> ports = intentAllocs.get(intentId);
intentAllocs.remove(intentId);
TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
for (Port port : ports) {
portAllocs.remove(port);
}
} catch (Exception e) {
log.error("Exception thrown, rolling back", e);
tx.abort();
throw e;
}
}
}
......@@ -17,6 +17,8 @@ import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Deactivate;
import org.onlab.util.Bandwidth;
import org.onosproject.net.OmsPort;
import org.onosproject.net.device.DeviceService;
import org.slf4j.Logger;
import org.onlab.util.KryoNamespace;
import org.onlab.util.PositionalParameterStringFormatter;
......@@ -55,7 +57,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.net.AnnotationKeys.BANDWIDTH;
import static org.onosproject.net.AnnotationKeys.OPTICAL_WAVES;
/**
* Store that manages link resources using Copycat-backed TransactionalMaps.
......@@ -78,7 +79,7 @@ public class ConsistentLinkResourceStore extends
// table to store current allocations
/** LinkKey -> List<LinkResourceAllocations>. */
private static final String LINK_RESOURCE_ALLOCATIONS = "LinkResourceAllocations";
private static final String LINK_RESOURCE_ALLOCATIONS = "o";
/** IntentId -> LinkResourceAllocations. */
private static final String INTENT_ALLOCATIONS = "IntentAllocations";
......@@ -95,6 +96,9 @@ public class ConsistentLinkResourceStore extends
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkService linkService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Activate
public void activate() {
intentAllocMap = storageService.<IntentId, LinkResourceAllocations>consistentMapBuilder()
......@@ -136,14 +140,14 @@ public class ConsistentLinkResourceStore extends
private Set<LambdaResourceAllocation> getLambdaResourceCapacity(Link link) {
Set<LambdaResourceAllocation> allocations = new HashSet<>();
try {
final int waves = Integer.parseInt(link.annotations().value(OPTICAL_WAVES));
for (int i = 1; i <= waves; i++) {
allocations.add(new LambdaResourceAllocation(LambdaResource.valueOf(i)));
}
} catch (NumberFormatException e) {
log.debug("No {} annotation on link {}", OPTICAL_WAVES, link);
OmsPort port = (OmsPort) deviceService.getPort(link.src().deviceId(), link.src().port());
// Assume fixed grid for now
for (int i = 0; i < port.totalChannels(); i++) {
allocations.add(new LambdaResourceAllocation(LambdaResource.valueOf(i)));
}
return allocations;
}
......
......@@ -54,12 +54,17 @@ class SmallOpticalTopo( Topo ):
self.addLink( O9, O10, port1=20, port2=20, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
self.addLink( SFOR10, O1, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
self.addLink( SFOR10, O1, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
self.addLink( LAXR10, O3, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
# added second tap
self.addLink( LAXR10, O3, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
self.addLink( SDGR10, O4, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
self.addLink( CHGR10, O7, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
self.addLink( JFKR10, O9, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
self.addLink( JFKR10, O9, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
self.addLink( ATLR10, O10, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
h1 = self.addHost( 'h1' )
......
......@@ -426,11 +426,15 @@ class LINCSwitch(OpticalSwitch):
response = json.load(urllib2.urlopen(url))
devs = response.get('devices')
# Wait for all devices to be registered & available
if (len(devices) == len(devs)):
for d in devs:
if not d['available']:
continue
# Wait for all devices to be registered
if (len(devices) != len(devs)):
continue
# Wait for all devices to available
available = True
for d in devs:
available &= d['available']
if available:
break
if (time >= TIMEOUT):
......
......@@ -138,6 +138,16 @@ public final class Frequency implements RichComparable<Frequency> {
return new Frequency(this.frequency * value);
}
/**
* Returns a Frequency whose value is Math.floorDiv(this, value).
*
* @param value
* @return Math.floorDiv(this, value)
*/
public Frequency floorDivision(long value) {
return new Frequency(Math.floorDiv(this.frequency, value));
}
@Override
public int compareTo(Frequency other) {
return ComparisonChain.start()
......