weibit

Optical Path Porvisioning

Change-Id: I9788fd9172edc8ab571aa1d41962c2bd10697c50
package org.onlab.onos.optical.provisioner;
import java.util.Iterator;
import java.util.Set;
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.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.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.topology.TopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* OpticalPathProvisioner listens event notifications from the Intent F/W.
* It generates one or more opticalConnectivityIntent(s) and submits (or withdraws) to Intent F/W
* for adding/releasing capacity at the packet layer.
*
*/
@Component(immediate = true)
public class OpticalPathProvisioner {
protected static final Logger log = LoggerFactory
.getLogger(OpticalPathProvisioner.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private IntentExtensionService intentExtensionService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkService linkService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
// protected LinkResourceService resourceService;
private ApplicationId appId;
private static long intentId = 0x9000000;
protected IdGenerator<IntentId> intentIdGenerator;
private final InternalOpticalPathProvisioner pathProvisioner = new InternalOpticalPathProvisioner();
@Activate
protected void activate() {
intentService.addListener(pathProvisioner);
appId = coreService.registerApplication("org.onlab.onos.optical");
log.info("Starting optical path provisoning...");
}
@Deactivate
protected void deactivate() {
intentService.removeListener(pathProvisioner);
}
public class InternalOpticalPathProvisioner implements IntentListener {
@Override
public void event(IntentEvent event) {
switch (event.type()) {
case SUBMITTED:
break;
case INSTALLED:
break;
case FAILED:
log.info("intent {} failed, calling optical path provisioning APP.", event.subject());
setuplightpath(event.subject());
break;
case WITHDRAWN:
log.info("intent {} withdrawn.", event.subject());
teardownLightpath(event.subject());
break;
default:
break;
}
}
private void setuplightpath(Intent intent) {
// TODO: considering user policies and optical reach, may generate more OpticalConnectivityIntents
if (!intent.equals(PointToPointIntent.class)) {
return;
}
PointToPointIntent pktIntent = (PointToPointIntent) intent;
if (pktIntent.ingressPoint() == null || pktIntent.egressPoint() == null) {
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()) {
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 = itrSrc.next().dst();
ConnectPoint dstWdmPoint = itrDst.next().dst();
OpticalConnectivityIntent opticalIntent =
new OpticalConnectivityIntent(new IntentId(intentId++),
srcWdmPoint,
dstWdmPoint);
log.info(opticalIntent.toString());
intentService.submit(opticalIntent);
}
private void teardownLightpath(Intent intent) {
// TODO: tear down the idle lightpath if the utilization is close to zero.
}
}
}
package org.onlab.onos.net.intent;
import org.onlab.onos.net.ConnectPoint;
/**
* An optical layer Intent for a connectivity from a Transponder port to another
* Transponder port. No trafficSelector as well as trafficTreament are needed.
*
*/
public class OpticalConnectivityIntent extends AbstractIntent {
protected ConnectPoint src;
protected ConnectPoint dst;
/**
* Constructor.
*
* @param id ID for this new Intent object.
* @param src The source transponder port.
* @param dst The destination transponder port.
*/
public OpticalConnectivityIntent(IntentId id, ConnectPoint src, ConnectPoint dst) {
super(id);
this.src = src;
this.dst = dst;
}
/**
* Constructor for serializer.
*/
protected OpticalConnectivityIntent() {
super();
this.src = null;
this.dst = null;
}
/**
* Gets source transponder port.
*
* @return The source transponder port.
*/
public ConnectPoint getSrcConnectPoint() {
return src;
}
/**
* Gets destination transponder port.
*
* @return The source transponder port.
*/
public ConnectPoint getDst() {
return dst;
}
}
package org.onlab.onos.net.intent;
import java.util.Collection;
import java.util.Objects;
import org.onlab.onos.net.ConnectPoint;
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 com.google.common.base.MoreObjects;
public class OpticalPathIntent extends OpticalConnectivityIntent implements InstallableIntent {
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) {
this.opticalMatch = match;
this.opticalAction = action;
this.path = path;
}
public OpticalPathIntent() {
this.opticalMatch = null;
this.opticalAction = null;
this.path = null;
}
public Path path() {
return path;
}
public TrafficSelector selector() {
return opticalMatch;
}
public TrafficTreatment treatment() {
return opticalAction;
}
@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;
}
return true;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), path);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("id", id())
.add("match", opticalMatch)
.add("action", opticalAction)
.add("ingressPort", this.getSrcConnectPoint())
.add("egressPort", this.getDst())
.add("path", path)
.toString();
}
@Override
public Collection<Link> requiredLinks() {
return path.links();
}
}
package org.onlab.onos.net.intent.impl;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
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.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.topology.PathService;
import org.slf4j.Logger;
/**
* Optical compiler for OpticalConnectivityIntent.
* It firstly computes K-shortest paths in the optical-layer, then choose the optimal one to assign a wavelength.
* Finally, it generates one or more opticalPathintent(s) with opticalMatchs and opticalActions.
*/
@Component(immediate = true)
public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
private final Logger log = getLogger(getClass());
private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentExtensionService intentManager;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PathService pathService;
// protected LinkResourceService resourceService;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
}
@Deactivate
public void deactivate() {
intentManager.unregisterCompiler(OpticalConnectivityIntent.class);
}
@Override
public List<Intent> compile(OpticalConnectivityIntent intent) {
// TO DO: compute multiple paths using the K-shortest path algorithm
Path path = calculatePath(intent.getSrcConnectPoint(), intent.getDst());
log.info("calculate the lightpath: {}.", 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,
path.src(),
path.dst(),
path);
retList.add(newIntent);
return retList;
}
private Path calculatePath(ConnectPoint one, ConnectPoint two) {
// TODO: K-shortest path computation algorithm
Set<Path> paths = pathService.getPaths(one.deviceId(), two.deviceId());
if (paths.isEmpty()) {
throw new PathNotFoundException("No optical path from " + one + " to " + two);
}
return paths.iterator().next();
}
private int assignWavelength(Path path) {
// TODO: wavelength assignment
return 1;
}
}
package org.onlab.onos.net.intent.impl;
import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Future;
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.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.flow.CompletedBatchOperation;
import org.onlab.onos.net.flow.DefaultFlowRule;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.FlowRuleBatchEntry;
import org.onlab.onos.net.flow.FlowRuleBatchOperation;
import org.onlab.onos.net.flow.FlowRuleService;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
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.slf4j.Logger;
import com.google.common.collect.Lists;
/**
* OpticaliIntentInstaller for optical path intents.
* It essentially generates optical FlowRules and
* call the flowRule service to execute them.
*/
@Component(immediate = true)
public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIntent> {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentExtensionService intentManager;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowRuleService flowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
private ApplicationId appId;
@Activate
public void activate() {
appId = coreService.registerApplication("org.onlab.onos.net.intent");
intentManager.registerInstaller(OpticalPathIntent.class, this);
}
@Deactivate
public void deactivate() {
intentManager.unregisterInstaller(OpticalPathIntent.class);
}
@Override
public Future<CompletedBatchOperation> install(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();
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, // priority is set to 100
appId,
100); // ROADM may need longer cross-connect time, here it is assumed 100ms.
rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
prev = link.dst();
}
FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
return future;
}
@Override
public Future<CompletedBatchOperation> 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();
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);
rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
prev = link.dst();
}
FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
return future;
}
}