[ONOS-4170] [ONOS-4163] PCE APP side changes : PceManager (code + UT)
Change-Id: I43db98b2fa3c5930b989d4fa3e2c00f7fa65c5ca
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/BasicPceccHandler.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/BasicPceccHandler.java
index 3ed670d..d7d18b1 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/BasicPceccHandler.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/BasicPceccHandler.java
@@ -23,13 +23,24 @@
import java.util.ListIterator;
import java.util.LinkedList;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.core.ApplicationId;
import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
import org.onosproject.incubator.net.resource.label.LabelResource;
import org.onosproject.incubator.net.resource.label.LabelResourceId;
import org.onosproject.incubator.net.resource.label.LabelResourceService;
import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
import org.onosproject.pce.pcestore.api.PceStore;
import org.onosproject.pce.pcestore.api.LspLocalLabelInfo;
import org.onosproject.pce.pcestore.PceccTunnelInfo;
@@ -58,6 +69,8 @@
private static BasicPceccHandler crHandlerInstance = null;
private LabelResourceService labelRsrcService;
private PceStore pceStore;
+ private FlowObjectiveService flowObjectiveService;
+ private ApplicationId appId;
/**
* Initializes default values.
@@ -83,8 +96,11 @@
* @param labelRsrcService label resource service
* @param pceStore pce label store
*/
- public void initialize(LabelResourceService labelRsrcService, PceStore pceStore) {
+ public void initialize(LabelResourceService labelRsrcService, FlowObjectiveService flowObjectiveService,
+ ApplicationId appId, PceStore pceStore) {
this.labelRsrcService = labelRsrcService;
+ this.flowObjectiveService = flowObjectiveService;
+ this.appId = appId;
this.pceStore = pceStore;
}
@@ -106,8 +122,8 @@
if ((linkList != null) && (linkList.size() > 0)) {
// Sequence through reverse order to push local labels into devices
// Generation of labels from egress to ingress
- for (ListIterator iterator = linkList.listIterator(linkList.size()); iterator.hasPrevious();) {
- Link link = (Link) iterator.previous();
+ for (ListIterator<Link> iterator = linkList.listIterator(linkList.size()); iterator.hasPrevious();) {
+ Link link = iterator.previous();
DeviceId dstDeviceId = link.dst().deviceId();
DeviceId srcDeviceId = link.src().deviceId();
labelRscList = labelRsrcService.applyFromDevicePool(dstDeviceId, applyNum);
@@ -131,16 +147,14 @@
}
// Push into destination device
- //TODO: uncomment below lines once installLocalLabelRule() method is ready
// Destination device IN port is link.dst().port()
- //installLocalLabelRule(dstDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
- // LabelType.IN, Objective.Operation.ADD);
+ installLocalLabelRule(dstDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
+ Long.valueOf(LabelType.IN_LABEL.value), Objective.Operation.ADD);
// Push into source device
- //TODO: uncomment below lines once installLocalLabelRule() method is ready
// Source device OUT port will be link.dst().port(). Means its remote port used to send packet.
- //installLocalLabelRule(srcDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
- // LabelType.OUT, Objective.Operation.ADD);
+ installLocalLabelRule(srcDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
+ Long.valueOf(LabelType.OUT_LABEL.value), Objective.Operation.ADD);
// Add or update pcecc tunnel info in pce store.
updatePceccTunnelInfoInStore(srcDeviceId, dstDeviceId, labelId, dstPort,
@@ -183,7 +197,7 @@
if ((lspLabelInfoList != null) && (lspLabelInfoList.size() > 0)) {
for (int i = 0; i < lspLabelInfoList.size(); ++i) {
LspLocalLabelInfo lspLocalLabelInfo =
- (DefaultLspLocalLabelInfo) lspLabelInfoList.get(i);
+ lspLabelInfoList.get(i);
LspLocalLabelInfo.Builder lspLocalLabelInfoBuilder = null;
if (dstDeviceId.equals(lspLocalLabelInfo.deviceId())) {
lspLocalLabelInfoBuilder = DefaultLspLocalLabelInfo.builder(lspLocalLabelInfo);
@@ -264,7 +278,7 @@
List<LspLocalLabelInfo> lspLocalLabelInfoList = pceccTunnelInfo.lspLocalLabelInfoList();
if ((lspLocalLabelInfoList != null) && (lspLocalLabelInfoList.size() > 0)) {
for (Iterator<LspLocalLabelInfo> iterator = lspLocalLabelInfoList.iterator(); iterator.hasNext();) {
- LspLocalLabelInfo lspLocalLabelInfo = (DefaultLspLocalLabelInfo) iterator.next();
+ LspLocalLabelInfo lspLocalLabelInfo = iterator.next();
DeviceId deviceId = lspLocalLabelInfo.deviceId();
LabelResourceId inLabelId = lspLocalLabelInfo.inLabelId();
LabelResourceId outLabelId = lspLocalLabelInfo.outLabelId();
@@ -278,15 +292,13 @@
// Push into device
if ((inLabelId != null) && (inPort != null)) {
- //TODO: uncomment below lines once installLocalLabelRule() method is ready
- //installLocalLabelRule(deviceId, inLabelId, inPort, tunnelId, isLastLabelToPush,
- // LabelType.IN, Objective.Operation.REMOVE);
+ installLocalLabelRule(deviceId, inLabelId, inPort, tunnel.tunnelId(), isLastLabelToPush,
+ Long.valueOf(LabelType.IN_LABEL.value), Objective.Operation.REMOVE);
}
if ((outLabelId != null) && (outPort != null)) {
- //TODO: uncomment below lines once installLocalLabelRule() method is ready
- //installLocalLabelRule(deviceId, outLabelId, outPort, tunnelId, isLastLabelToPush,
- // LabelType.OUT, Objective.Operation.REMOVE);
+ installLocalLabelRule(deviceId, outLabelId, outPort, tunnel.tunnelId(), isLastLabelToPush,
+ Long.valueOf(LabelType.OUT_LABEL.value), Objective.Operation.REMOVE);
}
// List is stored from egress to ingress. So, using IN label id to release.
@@ -315,4 +327,35 @@
log.error("Unable to find PCECC tunnel info in store for a tunnel {}.", tunnel.toString());
}
}
+
+ // Install a rule for pushing local labels to the device which is specific to path.
+ private void installLocalLabelRule(DeviceId deviceId, LabelResourceId labelId,
+ PortNumber portNum, TunnelId tunnelId,
+ Boolean isBos, Long labelType,
+ Objective.Operation type) {
+ checkNotNull(flowObjectiveService);
+ checkNotNull(appId);
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+ selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
+ selectorBuilder.matchInPort(portNum);
+ selectorBuilder.matchTunnelId(Long.parseLong(tunnelId.id()));
+ selectorBuilder.matchMplsBos(isBos);
+ selectorBuilder.matchMetadata(labelType);
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+
+ ForwardingObjective.Builder forwardingObjective = DefaultForwardingObjective.builder()
+ .withSelector(selectorBuilder.build())
+ .withTreatment(treatment)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .makePermanent();
+
+ if (type.equals(Objective.Operation.ADD)) {
+ flowObjectiveService.forward(deviceId, forwardingObjective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, forwardingObjective.remove());
+ }
+ }
}
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
index 7ea9934..904371d 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
@@ -16,11 +16,15 @@
package org.onosproject.pce.pceservice;
import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
+import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Map.Entry;
import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
@@ -29,22 +33,53 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.util.Bandwidth;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
import org.onosproject.core.IdGenerator;
+import org.onosproject.incubator.net.tunnel.DefaultTunnel;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.LabelStack;
import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelEvent;
import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelListener;
+import org.onosproject.incubator.net.tunnel.TunnelName;
import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultAnnotations.Builder;
+import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
import org.onosproject.net.Path;
-import org.onosproject.net.intent.Constraint;
import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
+import org.onosproject.pce.pceservice.constraint.CapabilityConstraint.CapabilityType;
+import org.onosproject.pce.pceservice.constraint.CostConstraint;
+import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.net.resource.ResourceQueryService;
import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.pce.pceservice.api.PceService;
-import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
+import org.onosproject.pce.pcestore.PcePathInfo;
+import org.onosproject.pce.pcestore.PceccTunnelInfo;
+import org.onosproject.pce.pcestore.api.PceStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.Serializer;
@@ -53,6 +88,29 @@
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.INIT;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.ESTABLISHED;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
+import static org.onosproject.pce.pceservice.LspType.WITH_SIGNALLING;
+import static org.onosproject.pce.pceservice.LspType.SR_WITHOUT_SIGNALLING;
+import static org.onosproject.pce.pceservice.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
+
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.BANDWIDTH;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LSP_SIG_TYPE;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCE_INIT;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCC_TUNNEL_ID;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.DELEGATE;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.COST_TYPE;
+
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
/**
* Implementation of PCE service.
@@ -63,8 +121,17 @@
private static final Logger log = LoggerFactory.getLogger(PceManager.class);
public static final String PCE_SERVICE_APP = "org.onosproject.pce";
-
private static final String LOCAL_LSP_ID_GEN_TOPIC = "pcep-local-lsp-id";
+ private static final int PREFIX_LENGTH = 32;
+
+ private static final String TUNNEL_CONSUMER_ID_GEN_TOPIC = "pcep-tunnel-consumer-id";
+ private IdGenerator tunnelConsumerIdGen;
+
+ private static final String LSRID = "lsrId";
+ private static final String TRUE = "true";
+ private static final String FALSE = "false";
+ private static final String END_OF_SYNC_IP_PREFIX = "0.0.0.0/32";
+
private IdGenerator localLspIdIdGen;
protected DistributedSet<Short> localLspIdFreeList;
@@ -72,22 +139,45 @@
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ResourceService resourceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ResourceQueryService resourceQueryService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PathService pathService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PceStore pceStore;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TunnelService tunnelService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected PathService pathService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ResourceService resourceService;
+ protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LabelResourceAdminService labelRsrcAdminService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LabelResourceService labelRsrcService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ private TunnelListener listener = new InnerTunnelListener();
+ private BasicPceccHandler crHandler;
+ private PceccSrTeBeHandler srTeHandler;
private ApplicationId appId;
+ private final PcepPacketProcessor processor = new PcepPacketProcessor();
+
/**
* Creates new instance of PceManager.
*/
@@ -97,18 +187,30 @@
@Activate
protected void activate() {
appId = coreService.registerApplication(PCE_SERVICE_APP);
- log.info("Started");
+ crHandler = BasicPceccHandler.getInstance();
+ crHandler.initialize(labelRsrcService, flowObjectiveService, appId, pceStore);
+ srTeHandler = PceccSrTeBeHandler.getInstance();
+ srTeHandler.initialize(labelRsrcAdminService, labelRsrcService, flowObjectiveService, appId, pceStore);
+
+ tunnelService.addListener(listener);
+
+ tunnelConsumerIdGen = coreService.getIdGenerator(TUNNEL_CONSUMER_ID_GEN_TOPIC);
localLspIdIdGen = coreService.getIdGenerator(LOCAL_LSP_ID_GEN_TOPIC);
localLspIdFreeList = storageService.<Short>setBuilder()
.withName("pcepLocalLspIdDeletedList")
.withSerializer(Serializer.using(KryoNamespaces.API))
.build()
.asDistributedSet();
+
+ packetService.addProcessor(processor, PacketProcessor.director(4));
+ log.info("Started");
}
@Deactivate
protected void deactivate() {
+ tunnelService.removeListener(listener);
+ packetService.removeProcessor(processor);
log.info("Stopped");
}
@@ -133,13 +235,13 @@
*/
protected Set<Path> computePath(DeviceId src, DeviceId dst, List<Constraint> constraints) {
if (pathService == null) {
- return null;
+ return ImmutableSet.of();
}
Set<Path> paths = pathService.getPaths(src, dst, weight(constraints));
if (!paths.isEmpty()) {
return paths;
}
- return null;
+ return ImmutableSet.of();
}
//[TODO:] handle requests in queue
@@ -149,22 +251,264 @@
checkNotNull(src);
checkNotNull(dst);
checkNotNull(tunnelName);
- checkNotNull(constraints);
checkNotNull(lspType);
- // TODO: compute and setup path.
- //TODO: gets the path based on constraints and creates a tunnel in network via tunnel manager
- return computePath(src, dst, constraints) != null ? true : false;
- }
+ // Convert from DeviceId to TunnelEndPoint
+ Device srcDevice = deviceService.getDevice(src);
+ Device dstDevice = deviceService.getDevice(dst);
+ if (srcDevice == null || dstDevice == null) {
+ // Device is not known.
+ pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+ return false;
+ }
+
+ // In future projections instead of annotations will be used to fetch LSR ID.
+ String srcLsrId = srcDevice.annotations().value(LSRID);
+ String dstLsrId = dstDevice.annotations().value(LSRID);
+
+ if (srcLsrId == null || dstLsrId == null) {
+ // LSR id is not known.
+ pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+ return false;
+ }
+
+ TunnelEndPoint srcEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(srcLsrId));
+ TunnelEndPoint dstEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(dstLsrId));
+
+ double bwConstraintValue = 0;
+ CostConstraint costConstraint = null;
+ if (constraints != null) {
+ constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
+ Iterator<Constraint> iterator = constraints.iterator();
+
+ while (iterator.hasNext()) {
+ Constraint constraint = iterator.next();
+ if (constraint instanceof BandwidthConstraint) {
+ bwConstraintValue = ((BandwidthConstraint) constraint).bandwidth().bps();
+ } else if (constraint instanceof CostConstraint) {
+ costConstraint = (CostConstraint) constraint;
+ }
+ }
+
+ /*
+ * Add cost at the end of the list of constraints. The path computation algorithm also computes cumulative
+ * cost. The function which checks the limiting/capability constraints also returns per link cost. This
+ * function can either return the result of limiting/capability constraint validation or the value of link
+ * cost, depending upon what is the last constraint in the loop.
+ */
+ if (costConstraint != null) {
+ constraints.remove(costConstraint);
+ constraints.add(costConstraint);
+ }
+ } else {
+ constraints = new LinkedList<>();
+ constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
+ }
+
+ Set<Path> computedPathSet = computePath(src, dst, constraints);
+
+ // NO-PATH
+ if (computedPathSet.isEmpty()) {
+ pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+ return false;
+ }
+
+ Builder annotationBuilder = DefaultAnnotations.builder();
+ if (bwConstraintValue != 0) {
+ annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
+ }
+ if (costConstraint != null) {
+ annotationBuilder.set(COST_TYPE, String.valueOf(costConstraint.type()));
+ }
+ annotationBuilder.set(LSP_SIG_TYPE, lspType.name());
+ annotationBuilder.set(PCE_INIT, TRUE);
+ annotationBuilder.set(DELEGATE, TRUE);
+
+ Path computedPath = computedPathSet.iterator().next();
+ LabelStack labelStack = null;
+
+ if (lspType == SR_WITHOUT_SIGNALLING) {
+ labelStack = srTeHandler.computeLabelStack(computedPath);
+ // Failed to form a label stack.
+ if (labelStack == null) {
+ pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+ return false;
+ }
+ }
+
+ if (lspType != WITH_SIGNALLING) {
+ /*
+ * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
+ * PCE for non-RSVP signalled LSPs.
+ */
+ annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(getNextLocalLspId()));
+ }
+
+ // For SR-TE tunnels, call SR manager for label stack and put it inside tunnel.
+ Tunnel tunnel = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
+ TunnelName.tunnelName(tunnelName), computedPath,
+ labelStack, annotationBuilder.build());
+
+ // Allocate bandwidth.
+ TunnelConsumerId consumerId = null;
+ if (bwConstraintValue != 0) {
+ consumerId = reserveBandwidth(computedPath, bwConstraintValue, null);
+ if (consumerId == null) {
+ pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+ return false;
+ }
+ }
+
+ TunnelId tunnelId = tunnelService.setupTunnel(appId, src, tunnel, computedPath);
+ if (tunnelId == null) {
+ pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+ if (consumerId != null) {
+ resourceService.release(consumerId);
+ }
+ return false;
+ }
+
+ if (consumerId != null) {
+ // Store tunnel consumer id in LSP-Label store.
+ PceccTunnelInfo pceccTunnelInfo = new PceccTunnelInfo(null, consumerId);
+ pceStore.addTunnelInfo(tunnelId, pceccTunnelInfo);
+ }
+ return true;
+ }
@Override
public boolean updatePath(TunnelId tunnelId, List<Constraint> constraints) {
checkNotNull(tunnelId);
- checkNotNull(constraints);
+ Set<Path> computedPathSet = null;
+ Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
- // TODO: compute and update path.
+ if (tunnel == null) {
+ return false;
+ }
+ if (tunnel.type() != MPLS || FALSE.equalsIgnoreCase(tunnel.annotations().value(DELEGATE))) {
+ // Only delegated LSPs can be updated.
+ return false;
+ }
+
+ List<Link> links = tunnel.path().links();
+ String lspSigType = tunnel.annotations().value(LSP_SIG_TYPE);
+ double bwConstraintValue = 0;
+ SharedBandwidthConstraint shBwConstraint = null;
+ BandwidthConstraint bwConstraint = null;
+ CostConstraint costConstraint = null;
+
+ if (constraints != null) {
+ // Call path computation in shared bandwidth mode.
+ Iterator<Constraint> iterator = constraints.iterator();
+ while (iterator.hasNext()) {
+ Constraint constraint = iterator.next();
+ if (constraint instanceof BandwidthConstraint) {
+ bwConstraint = (BandwidthConstraint) constraint;
+ bwConstraintValue = bwConstraint.bandwidth().bps();
+ } else if (constraint instanceof CostConstraint) {
+ costConstraint = (CostConstraint) constraint;
+ }
+ }
+
+ // Remove and keep the cost constraint at the end of the list of constraints.
+ if (costConstraint != null) {
+ constraints.remove(costConstraint);
+ }
+
+ Bandwidth existingBwValue = null;
+ String existingBwAnnotation = tunnel.annotations().value(BANDWIDTH);
+ if (existingBwAnnotation != null) {
+ existingBwValue = Bandwidth.bps(Double.parseDouble(existingBwAnnotation));
+
+ /*
+ * The computation is a shared bandwidth constraint based, so need to remove bandwidth constraint which
+ * has been utilized to create shared bandwidth constraint.
+ */
+ if (bwConstraint != null) {
+ constraints.remove(bwConstraint);
+ }
+ }
+
+ if (existingBwValue != null) {
+ shBwConstraint = new SharedBandwidthConstraint(links, existingBwValue, bwConstraint.bandwidth());
+ constraints.add(shBwConstraint);
+ }
+ } else {
+ constraints = new LinkedList<>();
+ }
+
+ constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspSigType)));
+ if (costConstraint != null) {
+ constraints.add(costConstraint);
+ }
+
+ computedPathSet = computePath(links.get(0).src().deviceId(), links.get(links.size() - 1).dst().deviceId(),
+ constraints);
+
+ // NO-PATH
+ if (computedPathSet.isEmpty()) {
+ return false;
+ }
+
+ Builder annotationBuilder = DefaultAnnotations.builder();
+ annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
+ annotationBuilder.set(LSP_SIG_TYPE, lspSigType);
+ annotationBuilder.set(PCE_INIT, TRUE);
+ annotationBuilder.set(DELEGATE, TRUE);
+ annotationBuilder.set(PLSP_ID, tunnel.annotations().value(PLSP_ID));
+ annotationBuilder.set(PCC_TUNNEL_ID, tunnel.annotations().value(PCC_TUNNEL_ID));
+
+ Path computedPath = computedPathSet.iterator().next();
+ LabelStack labelStack = null;
+ TunnelConsumerId consumerId = null;
+ LspType lspType = LspType.valueOf(lspSigType);
+ long localLspId = 0;
+ if (lspType != WITH_SIGNALLING) {
+ /*
+ * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
+ * PCE for non-RSVP signalled LSPs.
+ */
+ localLspId = getNextLocalLspId();
+ annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(localLspId));
+
+ if (lspType == SR_WITHOUT_SIGNALLING) {
+ labelStack = srTeHandler.computeLabelStack(computedPath);
+ // Failed to form a label stack.
+ if (labelStack == null) {
+ return false;
+ }
+ }
+ }
+
+ Tunnel updatedTunnel = new DefaultTunnel(null, tunnel.src(), tunnel.dst(), MPLS, INIT, null, null,
+ tunnel.tunnelName(), computedPath,
+ labelStack, annotationBuilder.build());
+
+ // Allocate shared bandwidth.
+ if (bwConstraintValue != 0) {
+ consumerId = reserveBandwidth(computedPath, bwConstraintValue, shBwConstraint);
+ if (consumerId == null) {
+ return false;
+ }
+ }
+
+ TunnelId updatedTunnelId = tunnelService.setupTunnel(appId, links.get(0).src().deviceId(), updatedTunnel,
+ computedPath);
+
+ if (updatedTunnelId == null) {
+ if (consumerId != null) {
+ resourceService.release(consumerId);
+ }
+ return false;
+ }
+
+ if (consumerId != null) {
+ // Store tunnel consumer id in LSP-Label store.
+ PceccTunnelInfo pceccTunnelInfo = new PceccTunnelInfo(null, consumerId);
+ pceStore.addTunnelInfo(updatedTunnelId, pceccTunnelInfo);
+ }
return true;
}
@@ -249,4 +593,281 @@
return cost;
}
}
+
+
+ // Allocates the bandwidth locally for PCECC tunnels.
+ private TunnelConsumerId reserveBandwidth(Path computedPath, double bandwidthConstraint,
+ SharedBandwidthConstraint shBwConstraint) {
+ checkNotNull(computedPath);
+ checkNotNull(bandwidthConstraint);
+ Resource resource = null;
+ double bwToAllocate = 0;
+
+ TunnelConsumerId consumer = TunnelConsumerId.valueOf(tunnelConsumerIdGen.getNewId());
+
+ /**
+ * Shared bandwidth sub-case : Lesser bandwidth required than original -
+ * No reservation required.
+ */
+ Double additionalBwValue = null;
+ if (shBwConstraint != null) {
+ additionalBwValue = ((bandwidthConstraint - shBwConstraint.sharedBwValue().bps()) <= 0) ? null
+ : (bandwidthConstraint - shBwConstraint.sharedBwValue().bps());
+ }
+
+ Optional<ResourceAllocation> resAlloc = null;
+ for (Link link : computedPath.links()) {
+ bwToAllocate = 0;
+ if ((shBwConstraint != null) && (shBwConstraint.links().contains(link))) {
+ if (additionalBwValue != null) {
+ bwToAllocate = bandwidthConstraint - additionalBwValue;
+ }
+ } else {
+ bwToAllocate = bandwidthConstraint;
+ }
+
+ /**
+ * In shared bandwidth cases, where new BW is lesser than old BW, it
+ * is not required to allocate anything.
+ */
+ if (bwToAllocate != 0) {
+ resource = Resources.continuous(link.src().deviceId(), link.src().port(), Bandwidth.class)
+ .resource(bwToAllocate);
+ resAlloc = resourceService.allocate(consumer, resource);
+
+ // If allocation for any link fails, then release the partially allocated bandwidth.
+ if (!resAlloc.isPresent()) {
+ resourceService.release(consumer);
+ return null;
+ }
+ }
+ }
+
+ /*
+ * Note: Storing of tunnel consumer id is done by caller of bandwidth reservation function. So deleting tunnel
+ * consumer id should be done by caller of bandwidth releasing function. This will prevent ambiguities related
+ * to who is supposed to store/delete.
+ */
+ return consumer;
+ }
+
+ /*
+ * Deallocates the bandwidth which is reserved locally for PCECC tunnels.
+ */
+ private void releaseBandwidth(Tunnel tunnel) {
+ // Between same source and destination, search the tunnel with same symbolic path name.
+ Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnel.src(), tunnel.dst());
+ Tunnel newTunnel = null;
+ for (Tunnel tunnelObj : tunnelQueryResult) {
+ if (tunnel.tunnelName().value().equals(tunnelObj.tunnelName().value())) {
+ newTunnel = tunnelObj;
+ break;
+ }
+ }
+
+ // Even if one link is shared, the bandwidth release should happen based on shared mechanism.
+ boolean isLinkShared = false;
+ if (newTunnel != null) {
+ for (Link link : tunnel.path().links()) {
+ if (newTunnel.path().links().contains(link)) {
+ isLinkShared = true;
+ break;
+ }
+ }
+ }
+
+ if (isLinkShared) {
+ releaseSharedBandwidth(newTunnel, tunnel);
+ return;
+ }
+
+ resourceService.release(pceStore.getTunnelInfo(tunnel.tunnelId()).tunnelConsumerId());
+ return;
+
+ /*
+ * Note: Storing of tunnel consumer id is done by caller of bandwidth reservation function. So deleting tunnel
+ * consumer id should be done by caller of bandwidth releasing function. This will prevent ambiguities related
+ * to who is supposed to store/delete.
+ */
+ }
+
+ /**
+ * Re-allocates the bandwidth for the tunnel for which the bandwidth was
+ * allocated in shared mode initially.
+ */
+ private synchronized void releaseSharedBandwidth(Tunnel newTunnel, Tunnel oldTunnel) {
+ // 1. Release old tunnel's bandwidth.
+ resourceService.release(pceStore.getTunnelInfo(oldTunnel.tunnelId()).tunnelConsumerId());
+
+ // 2. Release new tunnel's bandwidth
+ ResourceConsumer consumer = pceStore.getTunnelInfo(newTunnel.tunnelId()).tunnelConsumerId();
+ resourceService.release(consumer);
+
+ // 3. Allocate new tunnel's complete bandwidth.
+ double bandwidth = Double.parseDouble(newTunnel.annotations().value(BANDWIDTH));
+ Resource resource;
+
+ for (Link link : newTunnel.path().links()) {
+ resource = Resources.continuous(link.src().deviceId(), link.src().port(), Bandwidth.class)
+ .resource(bandwidth);
+ resourceService.allocate(consumer, resource); // Reusing new tunnel's TunnelConsumerId intentionally.
+ }
+ }
+
+ // Listens on tunnel events.
+ private class InnerTunnelListener implements TunnelListener {
+ @Override
+ public void event(TunnelEvent event) {
+ // Event gets generated with old tunnel object.
+ Tunnel tunnel = event.subject();
+ if (tunnel.type() != MPLS) {
+ return;
+ }
+
+ LspType lspType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));
+ String tunnelBandwidth = tunnel.annotations().value(BANDWIDTH);
+ double bwConstraintValue = 0;
+ if (tunnelBandwidth != null) {
+ bwConstraintValue = Double.parseDouble(tunnelBandwidth);
+ }
+
+ switch (event.type()) {
+ case TUNNEL_ADDED:
+ // Allocate bandwidth for non-initiated, delegated LSPs with non-zero bandwidth (learned LSPs).
+ String pceInit = tunnel.annotations().value(PCE_INIT);
+ if (FALSE.equalsIgnoreCase(pceInit)
+ && bwConstraintValue != 0) {
+ reserveBandwidth(tunnel.path(), bwConstraintValue, null);
+ }
+ break;
+
+ case TUNNEL_UPDATED:
+ // Allocate/send labels for basic PCECC tunnels.
+ if ((tunnel.state() == ESTABLISHED) && (lspType == WITHOUT_SIGNALLING_AND_WITHOUT_SR)) {
+ crHandler.allocateLabel(tunnel);
+ }
+
+ if (tunnel.state() == UNSTABLE) {
+ /*
+ * During LSP DB sync if PCC doesn't report LSP which was PCE initiated, it's state is turned into
+ * unstable so that it can be setup again. Add into failed path store so that it can be recomputed
+ * and setup while global reoptimization.
+ */
+
+ List<Constraint> constraints = new LinkedList<>();
+ String bandwidth = tunnel.annotations().value(BANDWIDTH);
+ if (bandwidth != null) {
+ constraints.add(new BandwidthConstraint(Bandwidth
+ .bps(Double.parseDouble(bandwidth))));
+ }
+
+ String costType = tunnel.annotations().value(COST_TYPE);
+ if (costType != null) {
+ CostConstraint costConstraint = new CostConstraint(CostConstraint.Type.valueOf(costType));
+ constraints.add(costConstraint);
+ }
+
+ constraints.add(CapabilityConstraint
+ .of(CapabilityType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))));
+
+ List<Link> links = tunnel.path().links();
+ pceStore.addFailedPathInfo(new PcePathInfo(links.get(0).src().deviceId(),
+ links.get(links.size() - 1).dst().deviceId(),
+ tunnel.tunnelName().value(), constraints, lspType));
+ }
+ break;
+
+ case TUNNEL_REMOVED:
+ if (lspType != WITH_SIGNALLING) {
+ localLspIdFreeList.add(Short.valueOf(tunnel.annotations().value(LOCAL_LSP_ID)));
+ }
+
+ // If not zero bandwidth, and delegated (initiated LSPs will also be delegated).
+ if (bwConstraintValue != 0) {
+ releaseBandwidth(event.subject());
+
+ // Release basic PCECC labels.
+ if (lspType == WITHOUT_SIGNALLING_AND_WITHOUT_SR) {
+ // Delete stored tunnel consumer id from PCE store (while still retaining label list.)
+ PceccTunnelInfo pceccTunnelInfo = pceStore.getTunnelInfo(tunnel.tunnelId());
+ pceccTunnelInfo.tunnelConsumerId(null);
+ crHandler.releaseLabel(tunnel);
+ } else {
+ pceStore.removeTunnelInfo(tunnel.tunnelId());
+ }
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ return;
+ }
+ }
+
+ private boolean syncLabelDb(DeviceId deviceId) {
+ checkNotNull(deviceId);
+ Map<DeviceId, LabelResourceId> globalNodeLabelMap = pceStore.getGlobalNodeLabels();
+
+ for (Entry<DeviceId, LabelResourceId> entry : globalNodeLabelMap.entrySet()) {
+
+ // Convert from DeviceId to TunnelEndPoint
+ Device srcDevice = deviceService.getDevice(entry.getKey());
+
+ /*
+ * If there is a slight difference in timing such that if device subsystem has removed the device but PCE
+ * store still has it, just ignore such devices.
+ */
+ if (srcDevice == null) {
+ continue;
+ }
+
+ String srcLsrId = srcDevice.annotations().value(LSRID);
+ if (srcLsrId == null) {
+ continue;
+ }
+
+ srTeHandler.advertiseNodeLabelRule(deviceId,
+ entry.getValue(),
+ IpPrefix.valueOf(IpAddress.valueOf(srcLsrId), PREFIX_LENGTH),
+ Objective.Operation.ADD, false);
+ }
+
+ Map<Link, LabelResourceId> adjLabelMap = pceStore.getAdjLabels();
+ for (Entry<Link, LabelResourceId> entry : adjLabelMap.entrySet()) {
+ if (entry.getKey().src().deviceId().equals(deviceId)) {
+ srTeHandler.installAdjLabelRule(deviceId,
+ entry.getValue(),
+ entry.getKey().src().port(),
+ entry.getKey().dst().port(),
+ Objective.Operation.ADD);
+ }
+ }
+
+ srTeHandler.advertiseNodeLabelRule(deviceId,
+ LabelResourceId.labelResourceId(0),
+ IpPrefix.valueOf(END_OF_SYNC_IP_PREFIX),
+ Objective.Operation.ADD, true);
+
+ return true;
+ }
+
+ // Process the packet received.
+ private class PcepPacketProcessor implements PacketProcessor {
+ // Process the packet received and in our case initiates the label DB sync.
+ @Override
+ public void process(PacketContext context) {
+ // Stop processing if the packet has been handled, since we
+ // can't do any more to it.
+
+ if (context.isHandled()) {
+ return;
+ }
+
+ InboundPacket pkt = context.inPacket();
+ syncLabelDb(pkt.receivedFrom().deviceId());
+ }
+ }
+
}
\ No newline at end of file
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
index 2a10dcf..51fd6dc 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
@@ -25,6 +25,11 @@
import java.util.Map;
import java.util.Set;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onosproject.core.ApplicationId;
import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
import org.onosproject.incubator.net.resource.label.LabelResource;
import org.onosproject.incubator.net.resource.label.LabelResourceId;
@@ -36,7 +41,15 @@
import org.onosproject.pce.pcestore.api.PceStore;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
-
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,7 +80,9 @@
private static PceccSrTeBeHandler srTeHandlerInstance = null;
private LabelResourceAdminService labelRsrcAdminService;
private LabelResourceService labelRsrcService;
+ private FlowObjectiveService flowObjectiveService;
private PceStore pceStore;
+ private ApplicationId appId;
/**
* Initializes default values.
@@ -95,10 +110,14 @@
* @param pceStore PCE label store
*/
public void initialize(LabelResourceAdminService labelRsrcAdminService,
- LabelResourceService labelRsrcService, PceStore pceStore) {
+ LabelResourceService labelRsrcService,
+ FlowObjectiveService flowObjectiveService,
+ ApplicationId appId, PceStore pceStore) {
this.labelRsrcAdminService = labelRsrcAdminService;
this.labelRsrcService = labelRsrcService;
+ this.flowObjectiveService = flowObjectiveService;
this.pceStore = pceStore;
+ this.appId = appId;
}
/**
@@ -152,15 +171,15 @@
}
pceStore.addGlobalNodeLabel(specificDeviceId, specificLabelId);
- //TODO: uncomment below line once advertiseNodeLabelRule() is ready
// Push its label information into specificDeviceId
- //advertiseNodeLabelRule(specificDeviceId, specificLabelId,
- // IpPrefix.valueOf(IpAddress.valueOf(specificLsrId), PREFIX_LENGTH),
+ advertiseNodeLabelRule(specificDeviceId, specificLabelId,
+ IpPrefix.valueOf(IpAddress.valueOf(specificLsrId), PREFIX_LENGTH),
+ Objective.Operation.ADD, false);
// Configure (node-label, lsr-id) mapping of each devices in list to specific device and vice versa.
- for (Map.Entry element:deviceIdLsrIdMap.entrySet()) {
- DeviceId otherDevId = (DeviceId) element.getKey();
- String otherLsrId = (String) element.getValue();
+ for (Map.Entry<DeviceId, String> element:deviceIdLsrIdMap.entrySet()) {
+ DeviceId otherDevId = element.getKey();
+ String otherLsrId = element.getValue();
if (otherLsrId == null) {
log.error("The lsr-id of device id {} is null.", otherDevId.toString());
releaseNodeLabel(specificDeviceId, specificLsrId, deviceIdLsrIdMap);
@@ -176,12 +195,11 @@
}
// Push to device
- // TODO: uncomment below line once advertiseNodeLabelRule() is ready
// Push label information of specificDeviceId to otherDevId in list and vice versa.
- //advertiseNodeLabelRule(otherDevId, specificLabelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
- // PREFIX_LENGTH), Objective.Operation.ADD);
- //advertiseNodeLabelRule(specificDeviceId, otherLabelId, IpPrefix.valueOf(IpAddress.valueOf(otherLsrId),
- // PREFIX_LENGTH), Objective.Operation.ADD);
+ advertiseNodeLabelRule(otherDevId, specificLabelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
+ PREFIX_LENGTH), Objective.Operation.ADD, false);
+ advertiseNodeLabelRule(specificDeviceId, otherLabelId, IpPrefix.valueOf(IpAddress.valueOf(otherLsrId),
+ PREFIX_LENGTH), Objective.Operation.ADD, false);
}
return true;
@@ -214,15 +232,14 @@
}
// Go through all devices in the map and remove label entry
- for (Map.Entry element:deviceIdLsrIdMap.entrySet()) {
- DeviceId otherDevId = (DeviceId) element.getKey();
+ for (Map.Entry<DeviceId, String> element:deviceIdLsrIdMap.entrySet()) {
+ DeviceId otherDevId = element.getKey();
// Remove this specific device label information from all other nodes except
// this specific node where connection already lost.
if (!specificDeviceId.equals(otherDevId)) {
- //TODO: uncomment below lines once advertiseNodeLabelRule() is ready
- //advertiseNodeLabelRule(otherDevId, labelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
- // PREFIX_LENGTH), Objective.Operation.REMOVE);
+ advertiseNodeLabelRule(otherDevId, labelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
+ PREFIX_LENGTH), Objective.Operation.REMOVE, false);
}
}
@@ -278,8 +295,7 @@
link.toString());
// Push adjacency label to device
- //TODO: uncomment below line once installAdjLabelRule() method is ready
- //installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.ADD);
+ installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.ADD);
// Save in store
pceStore.addAdjLabel(link, labelId);
@@ -309,8 +325,7 @@
DeviceId srcDeviceId = link.src().deviceId();
// Release adjacency label from device
- //TODO: uncomment below line once installAdjLabelRule() method is ready
- //installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.REMOVE);
+ installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.REMOVE);
// Release link label from label manager
Multimap<DeviceId, LabelResource> release = ArrayListMultimap.create();
@@ -350,7 +365,7 @@
LabelResourceId adjLabelId = null;
DeviceId deviceId = null;
for (Iterator<Link> iterator = linkList.iterator(); iterator.hasNext();) {
- link = (Link) iterator.next();
+ link = iterator.next();
// Add source device label now
deviceId = link.src().deviceId();
nodeLabelId = pceStore.getGlobalNodeLabel(deviceId);
@@ -386,4 +401,109 @@
}
return new DefaultLabelStack(labelStack);
}
+
+ /**
+ * Install a rule for pushing unique global labels to the device.
+ * @param deviceId device to which flow should be pushed
+ * @param labelId label for the device
+ * @param type type of operation
+ */
+ private void installNodeLabelRule(DeviceId deviceId, LabelResourceId labelId, Objective.Operation type) {
+ checkNotNull(flowObjectiveService);
+ checkNotNull(appId);
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+ selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .build();
+
+ ForwardingObjective.Builder forwardingObjective = DefaultForwardingObjective.builder()
+ .withSelector(selectorBuilder.build())
+ .withTreatment(treatment)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .makePermanent();
+
+ if (type.equals(Objective.Operation.ADD)) {
+
+ flowObjectiveService.forward(deviceId, forwardingObjective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, forwardingObjective.remove());
+ }
+ }
+
+ /**
+ * Install a rule for pushing node labels to the device of other nodes.
+ * @param deviceId device to which flow should be pushed
+ * @param labelId label for the device
+ * @param ipPrefix device for which label is pushed
+ * @param type type of operation
+ * @param bBos is this the end of sync push
+ */
+ public void advertiseNodeLabelRule(DeviceId deviceId, LabelResourceId labelId,
+ IpPrefix ipPrefix, Objective.Operation type, boolean bBos) {
+ checkNotNull(flowObjectiveService);
+ checkNotNull(appId);
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+ selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
+ selectorBuilder.matchIPSrc(ipPrefix);
+
+ if (bBos) {
+ selectorBuilder.matchMplsBos(bBos);
+ }
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .build();
+
+ ForwardingObjective.Builder forwardingObjective = DefaultForwardingObjective.builder()
+ .withSelector(selectorBuilder.build())
+ .withTreatment(treatment)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .makePermanent();
+
+ if (type.equals(Objective.Operation.ADD)) {
+ flowObjectiveService.forward(deviceId, forwardingObjective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, forwardingObjective.remove());
+ }
+ }
+
+ /**
+ * Install a rule for pushing Adjacency labels to the device.
+ * @param deviceId device to which flow should be pushed
+ * @param labelId label for the adjacency
+ * @param srcPortNum local port of the adjacency
+ * @param dstPortNum remote port of the adjacency
+ * @param type type of operation
+ */
+ public void installAdjLabelRule(DeviceId deviceId, LabelResourceId labelId,
+ PortNumber srcPortNum, PortNumber dstPortNum,
+ Objective.Operation type) {
+ checkNotNull(flowObjectiveService);
+ checkNotNull(appId);
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+ selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
+ selectorBuilder.matchTcpSrc(TpPort.tpPort((int) srcPortNum.toLong()));
+ selectorBuilder.matchTcpDst(TpPort.tpPort((int) dstPortNum.toLong()));
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .build();
+
+ ForwardingObjective.Builder forwardingObjective = DefaultForwardingObjective.builder()
+ .withSelector(selectorBuilder.build())
+ .withTreatment(treatment)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .makePermanent();
+
+ if (type.equals(Objective.Operation.ADD)) {
+ flowObjectiveService.forward(deviceId, forwardingObjective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, forwardingObjective.remove());
+ }
+ }
}
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcepAnnotationKeys.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcepAnnotationKeys.java
new file mode 100644
index 0000000..3eada9f
--- /dev/null
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcepAnnotationKeys.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016-present 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.pce.pceservice;
+
+/**
+ * Collection of keys for annotation for PCEP tunnels.
+ */
+public final class PcepAnnotationKeys {
+
+ /**
+ * Prohibits instantiation.
+ */
+ private PcepAnnotationKeys() {
+ }
+
+ /**
+ * Annotation key for bandwidth.
+ * The value for this key is interpreted as Mbps.
+ */
+ public static final String BANDWIDTH = "bandwidth";
+
+ /**
+ * Annotation key for the LSP signaling type.
+ */
+ public static final String LSP_SIG_TYPE = "lspSigType";
+
+ /**
+ * Annotation key for the PCC tunnel id.
+ */
+ public static final String PCC_TUNNEL_ID = "PccTunnelId";
+
+ /**
+ * Annotation key for the LSP id assigned per tunnel per session.
+ */
+ public static final String PLSP_ID = "PLspId";
+
+ /**
+ * Annotation key for the LSP id assigned per tunnel.
+ */
+ public static final String LOCAL_LSP_ID = "localLspId";
+
+ /**
+ * Annotation key for the identification of initiated LSP.
+ */
+ public static final String PCE_INIT = "pceInit";
+
+ /**
+ * Annotation key for the cost type.
+ */
+ public static final String COST_TYPE = "costType";
+
+ /**
+ * Annotation key for the Delegation.
+ * Whether LSPs are delegated or not.
+ */
+ public static final String DELEGATE = "delegate";
+}
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/TunnelConsumerId.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/TunnelConsumerId.java
index ddb5fad..e1a65b4 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/TunnelConsumerId.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/TunnelConsumerId.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.pce.pceservice;
+import org.onlab.util.Identifier;
import org.onosproject.net.resource.ResourceConsumer;
import com.google.common.annotations.Beta;
@@ -25,9 +26,7 @@
* resource allocations.
*/
@Beta
-public final class TunnelConsumerId implements ResourceConsumer {
-
- private final long value;
+public final class TunnelConsumerId extends Identifier<Long> implements ResourceConsumer {
/**
* Creates a tunnel resource consumer identifier from the specified long value.
@@ -43,7 +42,7 @@
* Initializes object for serializer.
*/
public TunnelConsumerId() {
- this.value = 0;
+ super(0L);
}
/**
@@ -54,43 +53,25 @@
* resource consumer id
*/
public TunnelConsumerId(long value) {
- this.value = value;
+ super(value);
}
/**
- * Returns the tunnel resource consumer id value in long format.
+ * Returns the backing identifier value.
*
- * @return value the tunnel resource consumer id's long value
+ * @return value backing identifier value
*/
public long value() {
- return value;
- }
-
- @Override
- public int hashCode() {
- return Long.hashCode(value);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
- if (!(obj instanceof TunnelConsumerId)) {
- return false;
- }
- TunnelConsumerId that = (TunnelConsumerId) obj;
- return this.value == that.value;
+ return identifier;
}
@Override
public String toString() {
- return "0x" + Long.toHexString(value);
+ return "0x" + Long.toHexString(identifier);
}
@Override
public ResourceConsumerId consumerId() {
- // TODO
- return null;
+ return ResourceConsumerId.of(this);
}
}
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/package-info.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/package-info.java
index 8eb75fa..ae5d9c7 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/package-info.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Open Networking Laboratory
+ * Copyright 2016-present 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.