Marc De Leenheer
Committed by Gerrit Code Review

Bidirectional optical intents (ONOS-2055).

Removed dead code.
Bugfix in device resource store.

Change-Id: Ic81e0b6985813d8dd696440610bee967a9fc2fc7
......@@ -58,9 +58,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
......@@ -106,9 +104,6 @@ public class OpticalPathProvisioner {
private ApplicationId appId;
private final Map<ConnectPoint, Map<ConnectPoint, Intent>> intentMap =
new ConcurrentHashMap<>();
private final InternalOpticalPathProvisioner pathProvisioner = new InternalOpticalPathProvisioner();
@Activate
......@@ -147,35 +142,13 @@ public class OpticalPathProvisioner {
break;
case WITHDRAWN:
log.info("Intent {} withdrawn.", event.subject());
withdrawIntent(event.subject());
releaseResources(event.subject());
break;
default:
break;
}
}
/**
* Registers an intent from src to dst.
*
* @param src source point
* @param dst destination point
* @param intent intent to be registered
* @return true if intent has not been previously added, false otherwise
*/
private boolean addIntent(ConnectPoint src, ConnectPoint dst, Intent intent) {
Map<ConnectPoint, Intent> srcMap = intentMap.get(src);
if (srcMap == null) {
srcMap = new ConcurrentHashMap<>();
intentMap.put(src, srcMap);
}
if (srcMap.containsKey(dst)) {
return false;
} else {
srcMap.put(dst, intent);
return true;
}
}
private void setupLightpath(Intent intent) {
checkNotNull(intent);
......@@ -310,14 +283,13 @@ public class OpticalPathProvisioner {
Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) {
// TODO: Check availability of ports
// Create OTN circuit
Intent circuitIntent = OpticalCircuitIntent.builder()
.appId(appId)
.src(src)
.dst(dst)
.signalType(OduCltPort.SignalType.CLT_10GBE)
.bidirectional(true)
.build();
intents.add(circuitIntent);
continue;
......@@ -329,6 +301,7 @@ public class OpticalPathProvisioner {
.src(src)
.dst(dst)
.signalType(OduSignalType.ODU4)
.bidirectional(true)
.build();
intents.add(opticalIntent);
continue;
......@@ -397,11 +370,11 @@ public class OpticalPathProvisioner {
}
/**
* Handle withdrawn intent on each network layer.
* Release resources associated to the given intent.
*
* @param intent the withdrawn intent
* @param intent the intent
*/
private void withdrawIntent(Intent intent) {
private void releaseResources(Intent intent) {
LinkResourceAllocations lra = linkResourceService.getAllocations(intent.id());
if (intent instanceof OpticalConnectivityIntent) {
deviceResourceService.releasePorts(intent.id());
......
......@@ -49,6 +49,7 @@ public class AddOpticalIntentCommand extends ConnectivityIntentCommand {
description = "Egress Device/Port Description",
required = true, multiValued = false)
String egressDeviceString = null;
// TODO: add parameter for uni/bidirectional intents
private ConnectPoint createConnectPoint(String devicePortString) {
String[] splitted = devicePortString.split("/");
......
......@@ -32,6 +32,7 @@ public class OpticalCircuitIntent extends Intent {
private final ConnectPoint src;
private final ConnectPoint dst;
private final OduCltPort.SignalType signalType;
private final boolean isBidirectional;
/**
* Creates an optical circuit intent between the specified
......@@ -45,11 +46,12 @@ public class OpticalCircuitIntent extends Intent {
* @param priority priority to use for flows from this intent
*/
protected OpticalCircuitIntent(ApplicationId appId, Key key, ConnectPoint src, ConnectPoint dst,
OduCltPort.SignalType signalType, int priority) {
OduCltPort.SignalType signalType, boolean isBidirectional, int priority) {
super(appId, key, Collections.emptyList(), priority);
this.src = checkNotNull(src);
this.dst = checkNotNull(dst);
this.signalType = checkNotNull(signalType);
this.isBidirectional = isBidirectional;
}
/**
......@@ -69,6 +71,7 @@ public class OpticalCircuitIntent extends Intent {
private ConnectPoint src;
private ConnectPoint dst;
private OduCltPort.SignalType signalType;
private boolean isBidirectional;
@Override
public Builder appId(ApplicationId appId) {
......@@ -119,6 +122,17 @@ public class OpticalCircuitIntent extends Intent {
}
/**
* Sets the directionality of the intent.
*
* @param isBidirectional true if bidirectional, false if unidirectional
* @return this builder
*/
public Builder bidirectional(boolean isBidirectional) {
this.isBidirectional = isBidirectional;
return this;
}
/**
* Builds an optical circuit intent from the accumulated parameters.
*
* @return point to point intent
......@@ -131,6 +145,7 @@ public class OpticalCircuitIntent extends Intent {
src,
dst,
signalType,
isBidirectional,
priority
);
}
......@@ -144,6 +159,7 @@ public class OpticalCircuitIntent extends Intent {
this.src = null;
this.dst = null;
this.signalType = null;
this.isBidirectional = false;
}
/**
......@@ -173,6 +189,15 @@ public class OpticalCircuitIntent extends Intent {
return signalType;
}
/**
* Returns the directionality of the intent.
*
* @return true if bidirectional, false if unidirectional
*/
public boolean isBidirectional() {
return isBidirectional;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
......@@ -184,6 +209,7 @@ public class OpticalCircuitIntent extends Intent {
.add("src", src)
.add("dst", dst)
.add("signalType", signalType)
.add("isBidirectional", isBidirectional)
.toString();
}
......
......@@ -32,6 +32,7 @@ public final class OpticalConnectivityIntent extends Intent {
private final ConnectPoint src;
private final ConnectPoint dst;
private final OduSignalType signalType;
private final boolean isBidirectional;
/**
* Creates an optical connectivity intent between the specified
......@@ -41,6 +42,7 @@ public final class OpticalConnectivityIntent extends Intent {
* @param key intent key
* @param src the source transponder port
* @param dst the destination transponder port
* @param isBidirectional indicates if intent is unidirectional
* @param priority priority to use for flows from this intent
*/
protected OpticalConnectivityIntent(ApplicationId appId,
......@@ -48,11 +50,13 @@ public final class OpticalConnectivityIntent extends Intent {
ConnectPoint src,
ConnectPoint dst,
OduSignalType signalType,
boolean isBidirectional,
int priority) {
super(appId, key, Collections.emptyList(), priority);
this.src = checkNotNull(src);
this.dst = checkNotNull(dst);
this.signalType = checkNotNull(signalType);
this.isBidirectional = isBidirectional;
}
/**
......@@ -72,6 +76,7 @@ public final class OpticalConnectivityIntent extends Intent {
private ConnectPoint src;
private ConnectPoint dst;
private OduSignalType signalType;
private boolean isBidirectional;
@Override
public Builder appId(ApplicationId appId) {
......@@ -122,6 +127,17 @@ public final class OpticalConnectivityIntent extends Intent {
}
/**
* Sets the directionality of the intent.
*
* @param isBidirectional true if bidirectional, false if unidirectional
* @return this builder
*/
public Builder bidirectional(boolean isBidirectional) {
this.isBidirectional = isBidirectional;
return this;
}
/**
* Builds an optical connectivity intent from the accumulated parameters.
*
* @return point to point intent
......@@ -134,6 +150,7 @@ public final class OpticalConnectivityIntent extends Intent {
src,
dst,
signalType,
isBidirectional,
priority
);
}
......@@ -147,6 +164,7 @@ public final class OpticalConnectivityIntent extends Intent {
this.src = null;
this.dst = null;
this.signalType = null;
this.isBidirectional = false;
}
/**
......@@ -176,6 +194,15 @@ public final class OpticalConnectivityIntent extends Intent {
return signalType;
}
/**
* Returns the directionality of the intent.
*
* @return true if bidirectional, false if unidirectional
*/
public boolean isBidirectional() {
return isBidirectional;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
......@@ -187,6 +214,7 @@ public final class OpticalConnectivityIntent extends Intent {
.add("src", src)
.add("dst", dst)
.add("signalType", signalType)
.add("isBidirectional", isBidirectional)
.toString();
}
}
......
......@@ -33,6 +33,7 @@ public final class OpticalPathIntent extends Intent {
private final Path path;
private final OchSignal lambda;
private final OchSignalType signalType;
private final boolean isBidirectional;
private OpticalPathIntent(ApplicationId appId,
Key key,
......@@ -41,6 +42,7 @@ public final class OpticalPathIntent extends Intent {
Path path,
OchSignal lambda,
OchSignalType signalType,
boolean isBidirectional,
int priority) {
super(appId, key, ImmutableSet.copyOf(path.links()), priority);
this.src = checkNotNull(src);
......@@ -48,6 +50,7 @@ public final class OpticalPathIntent extends Intent {
this.path = checkNotNull(path);
this.lambda = checkNotNull(lambda);
this.signalType = checkNotNull(signalType);
this.isBidirectional = isBidirectional;
}
protected OpticalPathIntent() {
......@@ -56,6 +59,7 @@ public final class OpticalPathIntent extends Intent {
this.path = null;
this.lambda = null;
this.signalType = null;
this.isBidirectional = true;
}
/**
......@@ -77,6 +81,7 @@ public final class OpticalPathIntent extends Intent {
private Path path;
private OchSignal lambda;
private OchSignalType signalType;
private boolean isBidirectional;
Key key;
@Override
......@@ -150,6 +155,15 @@ public final class OpticalPathIntent extends Intent {
}
/**
* Sets the intent's direction.
* @return this builder
*/
public Builder bidirectional(boolean isBidirectional) {
this.isBidirectional = isBidirectional;
return this;
}
/**
* Builds an optical path intent from the accumulated parameters.
*
* @return optical path intent
......@@ -164,6 +178,7 @@ public final class OpticalPathIntent extends Intent {
path,
lambda,
signalType,
isBidirectional,
priority
);
}
......@@ -190,6 +205,10 @@ public final class OpticalPathIntent extends Intent {
return signalType;
}
public boolean isBidirectional() {
return isBidirectional;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
......@@ -202,6 +221,7 @@ public final class OpticalPathIntent extends Intent {
.add("path", path)
.add("lambda", lambda)
.add("signalType", signalType)
.add("isBidirectional", isBidirectional)
.toString();
}
}
......
......@@ -136,15 +136,23 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
.src(srcCP)
.dst(dstCP)
.signalType(OduSignalType.ODU4)
.bidirectional(intent.isBidirectional())
.build();
intents.add(connIntent);
}
// Create optical circuit intent
circuitIntent = new FlowRuleIntent(
appId,
createRules(src, connIntent.getSrc(), dst, connIntent.getDst()),
intent.resources());
List<FlowRule> rules = new LinkedList<>();
rules.add(connectPorts(src, connIntent.getSrc()));
rules.add(connectPorts(connIntent.getDst(), dst));
// Create flow rules for reverse path
if (intent.isBidirectional()) {
rules.add(connectPorts(connIntent.getSrc(), src));
rules.add(connectPorts(dst, connIntent.getDst()));
}
circuitIntent = new FlowRuleIntent(appId, rules, intent.resources());
// Save circuit to connectivity intent mapping
deviceResourceService.requestMapping(connIntent.id(), circuitIntent.id());
......@@ -236,40 +244,25 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
}
/**
* Builds flow rules for mapping between ODU and OCh ports.
* Builds flow rule for mapping between two ports.
*
* @param srcOdu
* @param dstOdu
* @return
* @param src source port
* @param dst destination port
* @return flow rules
*/
private List<FlowRule> createRules(ConnectPoint srcOdu, ConnectPoint srcOch,
ConnectPoint dstOdu, ConnectPoint dstOch) {
private FlowRule connectPorts(ConnectPoint src, ConnectPoint dst) {
checkArgument(src.deviceId().equals(dst.deviceId()));
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
// Source flow rule
selectorBuilder.matchInPort(srcOdu.port());
selectorBuilder.matchInPort(src.port());
//selectorBuilder.add(Criteria.matchCltSignalType)
treatmentBuilder.setOutput(srcOch.port());
treatmentBuilder.setOutput(dst.port());
//treatmentBuilder.add(Instructions.modL1OduSignalType)
FlowRule srcRule = DefaultFlowRule.builder()
.forDevice(srcOdu.deviceId())
.withSelector(selectorBuilder.build())
.withTreatment(treatmentBuilder.build())
.withPriority(100)
.fromApp(appId)
.makePermanent()
.build();
// Destination flow rule
selectorBuilder.matchInPort(dstOch.port());
//selectorBuilder.add(Criteria.matchOduSignalType)
treatmentBuilder.setOutput(dstOdu.port());
//treatmentBuilder.add(Instructions.modL1CltSignalType)
FlowRule dstRule = DefaultFlowRule.builder()
.forDevice(dstOdu.deviceId())
FlowRule flowRule = DefaultFlowRule.builder()
.forDevice(src.deviceId())
.withSelector(selectorBuilder.build())
.withTreatment(treatmentBuilder.build())
.withPriority(100)
......@@ -277,6 +270,6 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
.makePermanent()
.build();
return Arrays.<FlowRule>asList(srcRule, dstRule);
return flowRule;
}
}
......
......@@ -144,6 +144,7 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
.path(path)
.lambda(ochSignal)
.signalType(signalType)
.bidirectional(intent.isBidirectional())
.build();
return ImmutableList.of(newIntent);
......
......@@ -15,6 +15,7 @@
*/
package org.onosproject.net.intent.impl.compiler;
import com.google.common.collect.Lists;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -79,10 +80,21 @@ public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathInte
Set<LinkResourceAllocations> resources) {
log.debug("Compiling optical path intent between {} and {}", intent.src(), intent.dst());
return Collections.singletonList(
new FlowRuleIntent(appId, createRules(intent), intent.resources()));
// Create rules for forward and reverse path
List<FlowRule> rules = createRules(intent);
if (intent.isBidirectional()) {
rules.addAll(createReverseRules(intent));
}
return Collections.singletonList(new FlowRuleIntent(appId, createRules(intent), intent.resources()));
}
/**
* Create rules for the forward path of the intent.
*
* @param intent the intent
* @return list of flow rules
*/
private List<FlowRule> createRules(OpticalPathIntent intent) {
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchInPort(intent.src().port());
......@@ -128,4 +140,56 @@ public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathInte
return rules;
}
/**
* Create rules for the reverse path of the intent.
*
* @param intent the intent
* @return list of flow rules
*/
private List<FlowRule> createReverseRules(OpticalPathIntent intent) {
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchInPort(intent.dst().port());
List<FlowRule> rules = new LinkedList<>();
ConnectPoint current = intent.dst();
for (Link link : Lists.reverse(intent.path().links())) {
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
treatmentBuilder.add(Instructions.modL0Lambda(intent.lambda()));
treatmentBuilder.setOutput(link.dst().port());
FlowRule rule = DefaultFlowRule.builder()
.forDevice(current.deviceId())
.withSelector(selectorBuilder.build())
.withTreatment(treatmentBuilder.build())
.withPriority(100)
.fromApp(appId)
.makePermanent()
.build();
rules.add(rule);
current = link.src();
selectorBuilder.matchInPort(link.src().port());
selectorBuilder.add(Criteria.matchLambda(intent.lambda()));
selectorBuilder.add(Criteria.matchOchSignalType(intent.signalType()));
}
// Build the egress ROADM rule
TrafficTreatment.Builder treatmentLast = DefaultTrafficTreatment.builder();
treatmentLast.setOutput(intent.src().port());
FlowRule rule = new DefaultFlowRule.Builder()
.forDevice(intent.src().deviceId())
.withSelector(selectorBuilder.build())
.withTreatment(treatmentLast.build())
.withPriority(100)
.fromApp(appId)
.makePermanent()
.build();
rules.add(rule);
return rules;
}
}
......
......@@ -33,6 +33,7 @@ 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.onosproject.store.service.Versioned;
import org.slf4j.Logger;
import java.util.Collections;
......@@ -169,16 +170,16 @@ public class ConsistentDeviceResourceStore implements DeviceResourceStore {
@Override
public boolean allocateMapping(IntentId keyIntentId, IntentId valIntentId) {
Set<IntentId> intents = intentMapping.get(keyIntentId).value();
Versioned<Set<IntentId>> versionedIntents = intentMapping.get(keyIntentId);
if (intents == null) {
intents = Collections.singleton(valIntentId);
if (versionedIntents == null) {
intentMapping.put(keyIntentId, Collections.singleton(valIntentId));
} else {
intents.add(valIntentId);
versionedIntents.value().add(valIntentId);
intentMapping.put(keyIntentId, versionedIntents.value());
}
intentMapping.put(keyIntentId, intents);
return true;
}
......
......@@ -217,6 +217,7 @@ public final class KryoNamespaces {
.register(Optional.class)
.register(Collections.emptyList().getClass())
.register(Collections.unmodifiableSet(Collections.emptySet()).getClass())
.register(Collections.singleton(Object.class).getClass())
.build();
/**
......