weibit

optical intent module

Change-Id: Ifa405ab1d883b293d349f1b66d26a05a0724691f
package org.onlab.onos.optical.provisioner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
......@@ -9,25 +12,25 @@ 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.onos.ApplicationId;
import org.onlab.onos.CoreService;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.net.intent.IdGenerator;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentEvent;
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentListener;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.OpticalConnectivityIntent;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.net.link.LinkService;
import org.onlab.onos.net.resource.LinkResourceService;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.Topology;
import org.onlab.onos.net.topology.TopologyEdge;
import org.onlab.onos.net.topology.TopologyGraph;
import org.onlab.onos.net.topology.TopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -63,12 +66,12 @@ public class OpticalPathProvisioner {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
// protected LinkResourceService resourceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkResourceService resourceService;
private ApplicationId appId;
private static long intentId = 0x9000000;
protected IdGenerator<IntentId> intentIdGenerator;
//protected <IntentId> intentIdGenerator;
private final InternalOpticalPathProvisioner pathProvisioner = new InternalOpticalPathProvisioner();
......@@ -106,7 +109,7 @@ public class OpticalPathProvisioner {
}
private void setuplightpath(Intent intent) {
// TODO: considering user policies and optical reach, may generate more OpticalConnectivityIntents
// TODO: considering user policies and optical reach
if (!intent.equals(PointToPointIntent.class)) {
return;
}
......@@ -116,35 +119,103 @@ public class OpticalPathProvisioner {
return;
}
// Set<Port> port1 = deviceService.getPorts(pktIntent.ingressPoint().deviceId());
Set<Link> srcLink = linkService.getLinks(pktIntent.ingressPoint());
Set<Link> dstLink = linkService.getLinks(pktIntent.egressPoint());
if (srcLink.isEmpty() || dstLink.isEmpty()) {
Topology topology = topologyService.currentTopology();
TopologyGraph graph = topologyService.getGraph(topology);
LinkWeight weight = new LinkWeight() {
@Override
public double weight(TopologyEdge edge) {
boolean isOptical = false;
String t = edge.link().annotations().value("linkType");
if (t.equals("WDM")) {
isOptical = true;
}
if (isOptical) {
return 1000; // optical links
} else {
return 10; // packet links
}
}
};
Set<Path> paths = topologyService.getPaths(topology,
pktIntent.ingressPoint().deviceId(),
pktIntent.egressPoint().deviceId(),
weight);
if (paths.isEmpty()) {
return;
}
Iterator<Link> itrSrc = srcLink.iterator();
Iterator<Link> itrDst = dstLink.iterator();
if (!itrSrc.next().annotations().value("linkType").equals("PktOptLink")) {
return;
}
if (!itrDst.next().annotations().value("linkType").equals("PktOptLink")) {
return;
ConnectPoint srcWdmPoint = null;
ConnectPoint dstWdmPoint = null;
Iterator<Path> itrPath = paths.iterator();
Path firstPath = itrPath.next();
log.info(firstPath.toString());
ArrayList<Map<ConnectPoint, ConnectPoint>> connectionList = new ArrayList<>();
Iterator<Link> itrLink = firstPath.links().iterator();
while (itrLink.hasNext()) {
Link link1 = itrLink.next();
if (!isOpticalLink(link1)) {
continue;
} else {
srcWdmPoint = link1.dst();
dstWdmPoint = srcWdmPoint;
}
while (true) {
if (itrLink.hasNext()) {
Link link2 = itrLink.next();
dstWdmPoint = link2.src();
} else {
break;
}
if (itrLink.hasNext()) {
Link link3 = itrLink.next();
if (!isOpticalLink(link3)) {
break;
}
} else {
break;
}
}
Map<ConnectPoint, ConnectPoint> pair =
new HashMap<ConnectPoint, ConnectPoint>();
pair.put(srcWdmPoint, dstWdmPoint);
connectionList.add(pair);
}
ConnectPoint srcWdmPoint = itrSrc.next().dst();
ConnectPoint dstWdmPoint = itrDst.next().dst();
for (Map<ConnectPoint, ConnectPoint> map : connectionList) {
for (Entry<ConnectPoint, ConnectPoint> entry : map.entrySet()) {
ConnectPoint src = entry.getKey();
ConnectPoint dst = entry.getValue();
OpticalConnectivityIntent opticalIntent =
new OpticalConnectivityIntent(new IntentId(intentId++),
srcWdmPoint,
dstWdmPoint);
Intent opticalIntent = new OpticalConnectivityIntent(appId,
srcWdmPoint,
dstWdmPoint);
log.info(opticalIntent.toString());
intentService.submit(opticalIntent);
intentService.submit(opticalIntent);
log.info(opticalIntent.toString());
}
}
}
private boolean isOpticalLink(Link link) {
boolean isOptical = false;
String t = link.annotations().value("linkType");
if (t.equals("WDM") || t.equals("PktOptLink")) {
isOptical = true;
}
return isOptical;
}
private void teardownLightpath(Intent intent) {
......
package org.onlab.onos.net.intent;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
/**
* An optical layer Intent for a connectivity from a Transponder port to another
* An optical layer Intent for a connectivity from one Transponder port to another
* Transponder port. No trafficSelector as well as trafficTreament are needed.
*
*/
public class OpticalConnectivityIntent extends AbstractIntent {
public class OpticalConnectivityIntent extends Intent {
protected ConnectPoint src;
protected ConnectPoint dst;
......@@ -18,8 +19,9 @@ public class OpticalConnectivityIntent extends AbstractIntent {
* @param src The source transponder port.
* @param dst The destination transponder port.
*/
public OpticalConnectivityIntent(IntentId id, ConnectPoint src, ConnectPoint dst) {
super(id);
public OpticalConnectivityIntent(ApplicationId appId, ConnectPoint src, ConnectPoint dst) {
super(id(OpticalConnectivityIntent.class, src, dst),
appId, null);
this.src = src;
this.dst = dst;
}
......
package org.onlab.onos.net.intent;
import java.util.Collection;
import java.util.Objects;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
......@@ -11,15 +11,18 @@ import org.onlab.onos.net.flow.TrafficTreatment;
import com.google.common.base.MoreObjects;
public class OpticalPathIntent extends OpticalConnectivityIntent implements InstallableIntent {
public class OpticalPathIntent extends OpticalConnectivityIntent {
private final Path path;
private final TrafficSelector opticalMatch;
private final TrafficTreatment opticalAction;
public OpticalPathIntent(IntentId id, TrafficSelector match, TrafficTreatment action,
ConnectPoint ingressPort, ConnectPoint egressPort,
Path path) {
public OpticalPathIntent(ApplicationId appId,
ConnectPoint src,
ConnectPoint dst,
TrafficSelector match,
TrafficTreatment action,
Path path) {
super(appId, src, dst);
this.opticalMatch = match;
this.opticalAction = action;
this.path = path;
......@@ -44,32 +47,11 @@ public class OpticalPathIntent extends OpticalConnectivityIntent implements Inst
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
OpticalPathIntent that = (OpticalPathIntent) o;
if (!path.equals(that.path)) {
return false;
}
public boolean isInstallable() {
return true;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), path);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("id", id())
......@@ -81,7 +63,6 @@ public class OpticalPathIntent extends OpticalConnectivityIntent implements Inst
.toString();
}
@Override
public Collection<Link> requiredLinks() {
return path.links();
}
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.net.intent.impl;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
......@@ -12,24 +12,28 @@ 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.onos.CoreService;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultEdgeLink;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.IdGenerator;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentCompiler;
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.OpticalConnectivityIntent;
import org.onlab.onos.net.intent.OpticalPathIntent;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.resource.LinkResourceService;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.PathService;
import org.onlab.onos.net.topology.Topology;
import org.onlab.onos.net.topology.TopologyEdge;
import org.onlab.onos.net.topology.TopologyService;
import org.slf4j.Logger;
/**
......@@ -49,14 +53,17 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PathService pathService;
// protected LinkResourceService resourceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
protected IdGenerator<IntentId> intentIdGenerator;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkResourceService resourceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Activate
public void activate() {
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
}
......@@ -67,29 +74,29 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
@Override
public List<Intent> compile(OpticalConnectivityIntent intent) {
// TO DO: compute multiple paths using the K-shortest path algorithm
// TODO: compute multiple paths using the K-shortest path algorithm
List<Intent> retList = new ArrayList<>();
Path path = calculatePath(intent.getSrcConnectPoint(), intent.getDst());
log.info("calculate the lightpath: {}.", path.toString());
if (path == null) {
return retList;
} else {
log.info("the computed lightpath is : {}.", path.toString());
}
List<Link> links = new ArrayList<>();
links.add(DefaultEdgeLink.createEdgeLink(intent.getSrcConnectPoint(), true));
links.addAll(path.links());
links.add(DefaultEdgeLink.createEdgeLink(intent.getDst(), false));
// TO DO: choose a wavelength using the first-fit algorithm
TrafficSelector opticalSelector = null;
TrafficTreatment opticalTreatment = null;
List<Intent> retList = new ArrayList<>();
int wavelength = assignWavelength(path);
log.info("assign the wavelength: {}.", wavelength);
// create a new opticalPathIntent
Intent newIntent = new OpticalPathIntent(intentIdGenerator.getNewId(),
opticalSelector,
opticalTreatment,
Intent newIntent = new OpticalPathIntent(intent.appId(),
path.src(),
path.dst(),
opticalSelector,
opticalTreatment,
path);
retList.add(newIntent);
......@@ -97,18 +104,45 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
return retList;
}
private Path calculatePath(ConnectPoint one, ConnectPoint two) {
// TODO: K-shortest path computation algorithm
Set<Path> paths = pathService.getPaths(one.deviceId(), two.deviceId());
private Path calculatePath(ConnectPoint start, ConnectPoint end) {
// TODO: support user policies
Topology topology = topologyService.currentTopology();
LinkWeight weight = new LinkWeight() {
@Override
public double weight(TopologyEdge edge) {
boolean isOptical = false;
String t = edge.link().annotations().value("linkType");
if (t.equals("WDM")) {
isOptical = true;
}
if (isOptical) {
return 1; // optical links
} else {
return 10000; // packet links
}
}
};
Set<Path> paths = topologyService.getPaths(topology,
start.deviceId(),
end.deviceId(),
weight);
Iterator<Path> itr = paths.iterator();
while (itr.hasNext()) {
Path path = itr.next();
if (path.cost() >= 10000) {
itr.remove();
}
}
if (paths.isEmpty()) {
throw new PathNotFoundException("No optical path from " + one + " to " + two);
log.info("No optical path found from " + start + " to " + end);
return null;
} else {
return paths.iterator().next();
}
return paths.iterator().next();
}
private int assignWavelength(Path path) {
// TODO: wavelength assignment
return 1;
}
}
......
......@@ -19,6 +19,7 @@ import org.onlab.onos.net.Link;
import org.onlab.onos.net.flow.CompletedBatchOperation;
import org.onlab.onos.net.flow.DefaultFlowRule;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.FlowRuleBatchEntry;
import org.onlab.onos.net.flow.FlowRuleBatchOperation;
......@@ -29,6 +30,12 @@ import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.intent.IntentInstaller;
import org.onlab.onos.net.intent.OpticalPathIntent;
import org.onlab.onos.net.resource.Lambda;
import org.onlab.onos.net.resource.LinkResourceAllocations;
import org.onlab.onos.net.resource.LinkResourceRequest;
import org.onlab.onos.net.resource.LinkResourceService;
import org.onlab.onos.net.resource.ResourceRequest;
import org.onlab.onos.net.topology.TopologyService;
import org.slf4j.Logger;
import com.google.common.collect.Lists;
......@@ -41,7 +48,6 @@ import com.google.common.collect.Lists;
@Component(immediate = true)
public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIntent> {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......@@ -53,8 +59,16 @@ public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIn
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkResourceService resourceService;
private ApplicationId appId;
final static short WAVELENGTH = 80;
@Activate
public void activate() {
appId = coreService.registerApplication("org.onlab.onos.net.intent");
......@@ -67,12 +81,25 @@ public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIn
}
@Override
public Future<CompletedBatchOperation> install(OpticalPathIntent intent) {
public List<FlowRuleBatchOperation> install(OpticalPathIntent intent) {
Lambda la = assignWavelength(intent.path().links());
if (la == null) {
return null;
}
// resourceService.requestResources(la);
// la.toInt();
//intent.selector().criteria();
//TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
//builder.matchLambdaType(la.toInt())
// .matchInport(intent.getSrcConnectPoint().port());
TrafficSelector.Builder builder =
DefaultTrafficSelector.builder(intent.selector());
Iterator<Link> links = intent.path().links().iterator();
ConnectPoint prev = links.next().dst();
List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
// TODO Generate multiple batches
while (links.hasNext()) {
builder.matchInport(prev.port());
Link link = links.next();
......@@ -82,47 +109,77 @@ public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIn
FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
builder.build(),
treatment,
100, // priority is set to 100
100,
appId,
100); // ROADM may need longer cross-connect time, here it is assumed 100ms.
100,
true);
rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
prev = link.dst();
}
return Lists.newArrayList(new FlowRuleBatchOperation(rules));
}
FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
return future;
private Lambda assignWavelength(List<Link> links) {
// TODO More wavelength assignment algorithm
int wavenum = 0;
Iterator<Link> itrlink = links.iterator();
for (int i = 1; i <= WAVELENGTH; i++) {
wavenum = i;
boolean found = true;
while (itrlink.hasNext()) {
Link link = itrlink.next();
if (isWavelengthUsed(link, i)) {
found = false;
break;
}
}
// First-Fit wavelength assignment algorithm
if (found) {
break;
}
}
if (wavenum == 0) {
return null;
}
Lambda wave = Lambda.valueOf(wavenum);
return wave;
}
private boolean isWavelengthUsed(Link link, int i) {
Iterable<LinkResourceAllocations> wave = resourceService.getAllocations(link);
for (LinkResourceAllocations ir : wave) {
//if ir.resources().contains(i) {
//}
}
return false;
}
@Override
public Future<CompletedBatchOperation> uninstall(OpticalPathIntent intent) {
public List<FlowRuleBatchOperation> uninstall(OpticalPathIntent intent) {
TrafficSelector.Builder builder =
DefaultTrafficSelector.builder(intent.selector());
Iterator<Link> links = intent.path().links().iterator();
ConnectPoint prev = links.next().dst();
List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
// TODO Generate multiple batches
while (links.hasNext()) {
builder.matchInport(prev.port());
Link link = links.next();
TrafficTreatment treatment = builder()
.setOutput(link.src().port()).build();
FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
builder.build(),
treatment,
100,
appId,
100);
100,
true);
rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
prev = link.dst();
}
FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
return future;
return Lists.newArrayList(new FlowRuleBatchOperation(rules));
}
}
......