ONOS-631 #Initial MPLS intent implementation
Change-Id: I6f906b953f06f395cc67e612648802e333c0e581
diff --git a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/DistributedLinkResourceStore.java b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/DistributedLinkResourceStore.java
index 0119e1f..73b053d 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/DistributedLinkResourceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/DistributedLinkResourceStore.java
@@ -42,6 +42,8 @@
import org.onosproject.net.resource.LinkResourceAllocations;
import org.onosproject.net.resource.LinkResourceEvent;
import org.onosproject.net.resource.LinkResourceStore;
+import org.onosproject.net.resource.MplsLabel;
+import org.onosproject.net.resource.MplsLabelResourceAllocation;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceAllocationException;
import org.onosproject.net.resource.ResourceType;
@@ -105,9 +107,10 @@
// Link annotation key name to use as max lambda
private String wavesAnnotation = AnnotationKeys.OPTICAL_WAVES;
+ // Max MPLS labels: 2^20 – 1
+ private int maxMplsLabel = 0xFFFFF;
private StoreSerializer serializer;
-
void createTable(String tableName) {
boolean tableReady = false;
do {
@@ -150,6 +153,9 @@
if (type == ResourceType.LAMBDA) {
return getLambdaResourceCapacity(link);
}
+ if (type == ResourceType.MPLS_LABEL) {
+ return getMplsResourceCapacity();
+ }
return null;
}
@@ -189,6 +195,17 @@
return new BandwidthResourceAllocation(bandwidth);
}
+ private Set<MplsLabelResourceAllocation> getMplsResourceCapacity() {
+ Set<MplsLabelResourceAllocation> allocations = new HashSet<>();
+ //Ignoring reserved labels of 0 through 15
+ for (int i = 16; i <= maxMplsLabel; i++) {
+ allocations.add(new MplsLabelResourceAllocation(MplsLabel
+ .valueOf(i)));
+
+ }
+ return allocations;
+ }
+
private Map<ResourceType, Set<? extends ResourceAllocation>> getResourceCapacity(Link link) {
Map<ResourceType, Set<? extends ResourceAllocation>> caps = new HashMap<>();
for (ResourceType type : ResourceType.values()) {
@@ -273,6 +290,34 @@
free.put(type, freeL);
break;
}
+ case MPLS_LABEL:
+ {
+ Set<? extends ResourceAllocation> mpls = caps.get(type);
+ if (mpls == null || mpls.isEmpty()) {
+ // nothing left
+ break;
+ }
+ Set<MplsLabelResourceAllocation> freeLabel = new HashSet<>();
+ for (ResourceAllocation r : mpls) {
+ if (r instanceof MplsLabelResourceAllocation) {
+ freeLabel.add((MplsLabelResourceAllocation) r);
+ }
+ }
+
+ // enumerate current allocations, removing resources
+ for (LinkResourceAllocations alloc : allocations) {
+ Set<ResourceAllocation> types = alloc
+ .getResourceAllocation(link);
+ for (ResourceAllocation a : types) {
+ if (a instanceof MplsLabelResourceAllocation) {
+ freeLabel.remove(a);
+ }
+ }
+ }
+
+ free.put(type, freeLabel);
+ break;
+ }
default:
break;
@@ -298,7 +343,6 @@
encodeIntentAllocations(alloc));
}
-
@Override
public void allocateResources(LinkResourceAllocations allocations) {
checkNotNull(allocations);
@@ -313,8 +357,9 @@
}
BatchWriteRequest batch = tx.build();
-// log.info("Intent: {}", databaseService.getAll(INTENT_ALLOCATIONS));
-// log.info("Link: {}", databaseService.getAll(LINK_RESOURCE_ALLOCATIONS));
+// log.info("Intent: {}", databaseService.getAll(INTENT_ALLOCATIONS));
+// log.info("Link: {}",
+ // databaseService.getAll(LINK_RESOURCE_ALLOCATIONS));
BatchWriteResult result = databaseService.batchWrite(batch);
if (!result.isSuccessful()) {
@@ -407,6 +452,21 @@
link,
lambdaAllocation.lambda().toInt()));
}
+ } else if (req instanceof MplsLabelResourceAllocation) {
+
+ final MplsLabelResourceAllocation mplsAllocation = (MplsLabelResourceAllocation) req;
+ // check if allocation should be accepted
+ if (!avail.contains(req)) {
+ // requested mpls label was not available
+ throw new ResourceAllocationException(
+ PositionalParameterStringFormatter
+ .format("Unable to allocate MPLS label for "
+ + "link {} MPLS label is {}",
+ link,
+ mplsAllocation
+ .mplsLabel()
+ .toString()));
+ }
}
}
// all requests allocatable => add allocation
@@ -466,8 +526,7 @@
// Issue events to force recompilation of intents.
- final List<LinkResourceAllocations> releasedResources =
- ImmutableList.of(allocations);
+ final List<LinkResourceAllocations> releasedResources = ImmutableList.of(allocations);
return new LinkResourceEvent(
LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE,
releasedResources);
@@ -485,32 +544,32 @@
}
private String toLinkDbKey(LinkKey linkid) {
- // introduce cache if necessary
+// introduce cache if necessary
return linkid.toString();
- // Note: Above is irreversible, if we need reverse conversion
- // we may need something like below, due to String only limitation
-// byte[] bytes = serializer.encode(linkid);
-// StringBuilder builder = new StringBuilder(bytes.length * 4);
-// boolean isFirst = true;
-// for (byte b : bytes) {
-// if (!isFirst) {
-// builder.append(',');
-// }
-// builder.append(b);
-// isFirst = false;
-// }
-// return builder.toString();
+// Note: Above is irreversible, if we need reverse conversion
+// we may need something like below, due to String only limitation
+// byte[] bytes = serializer.encode(linkid);
+// StringBuilder builder = new StringBuilder(bytes.length * 4);
+// boolean isFirst = true;
+// for (byte b : bytes) {
+// if (!isFirst) {
+// builder.append(',');
+// }
+// builder.append(b);
+// isFirst = false;
+// }
+// return builder.toString();
}
-// private LinkKey toLinkKey(String linkKey) {
-// String[] bytes = linkKey.split(",");
-// ByteBuffer buf = ByteBuffer.allocate(bytes.length);
-// for (String bs : bytes) {
-// buf.put(Byte.parseByte(bs));
-// }
-// buf.flip();
-// return serializer.decode(buf);
-// }
+// private LinkKey toLinkKey(String linkKey) {
+// String[] bytes = linkKey.split(",");
+// ByteBuffer buf = ByteBuffer.allocate(bytes.length);
+// for (String bs : bytes) {
+// buf.put(Byte.parseByte(bs));
+// }
+// buf.flip();
+// return serializer.decode(buf);
+// }
private String toIntentDbKey(IntentId intentid) {
return intentid.toString();
@@ -565,16 +624,16 @@
Map<String, VersionedValue> all = databaseService.getAll(INTENT_ALLOCATIONS);
return FluentIterable.from(all.values())
- .transform(new Function<VersionedValue, LinkResourceAllocations>() {
+ .transform(new Function<VersionedValue, LinkResourceAllocations>() {
- @Override
- public LinkResourceAllocations apply(VersionedValue input) {
- if (input == null || input.value() == null) {
- return null;
- }
- return decodeIntentAllocations(input.value());
- }
- })
- .filter(notNull());
+ @Override
+ public LinkResourceAllocations apply(VersionedValue input) {
+ if (input == null || input.value() == null) {
+ return null;
+ }
+ return decodeIntentAllocations(input.value());
+ }
+ })
+ .filter(notNull());
}
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/HazelcastLinkResourceStore.java b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/HazelcastLinkResourceStore.java
index 7344862..52494dd 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/HazelcastLinkResourceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/HazelcastLinkResourceStore.java
@@ -43,6 +43,8 @@
import org.onosproject.net.resource.LinkResourceAllocations;
import org.onosproject.net.resource.LinkResourceEvent;
import org.onosproject.net.resource.LinkResourceStore;
+import org.onosproject.net.resource.MplsLabel;
+import org.onosproject.net.resource.MplsLabelResourceAllocation;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceAllocationException;
import org.onosproject.net.resource.ResourceType;
@@ -103,6 +105,9 @@
// Link annotation key name to use as max lambda
private String wavesAnnotation = AnnotationKeys.OPTICAL_WAVES;
+ // Max MPLS labels: 2^20 – 1
+ private int maxMplsLabel = 0xFFFFF;
+
@Override
@Activate
public void activate() {
@@ -141,6 +146,9 @@
if (type == ResourceType.LAMBDA) {
return getLambdaResourceCapacity(link);
}
+ if (type == ResourceType.MPLS_LABEL) {
+ return getMplsResourceCapacity();
+ }
return null;
}
@@ -180,6 +188,17 @@
return new BandwidthResourceAllocation(bandwidth);
}
+ private Set<MplsLabelResourceAllocation> getMplsResourceCapacity() {
+ Set<MplsLabelResourceAllocation> allocations = new HashSet<>();
+ //Ignoring reserved labels of 0 through 15
+ for (int i = 16; i <= maxMplsLabel; i++) {
+ allocations.add(new MplsLabelResourceAllocation(MplsLabel
+ .valueOf(i)));
+
+ }
+ return allocations;
+ }
+
private Map<ResourceType, Set<? extends ResourceAllocation>> getResourceCapacity(Link link) {
Map<ResourceType, Set<? extends ResourceAllocation>> caps = new HashMap<>();
for (ResourceType type : ResourceType.values()) {
@@ -275,6 +294,33 @@
break;
}
+ case MPLS_LABEL:
+ Set<? extends ResourceAllocation> mpls = caps.get(type);
+ if (mpls == null || mpls.isEmpty()) {
+ // nothing left
+ break;
+ }
+ Set<MplsLabelResourceAllocation> freeLabel = new HashSet<>();
+ for (ResourceAllocation r : mpls) {
+ if (r instanceof MplsLabelResourceAllocation) {
+ freeLabel.add((MplsLabelResourceAllocation) r);
+ }
+ }
+
+ // enumerate current allocations, removing resources
+ for (LinkResourceAllocations alloc : allocations) {
+ Set<ResourceAllocation> types = alloc
+ .getResourceAllocation(link);
+ for (ResourceAllocation a : types) {
+ if (a instanceof MplsLabelResourceAllocation) {
+ freeLabel.remove(a);
+ }
+ }
+ }
+
+ free.put(type, freeLabel);
+ break;
+
default:
break;
}
@@ -354,6 +400,18 @@
link,
lambdaAllocation.lambda().toInt()));
}
+ } else if (req instanceof MplsLabelResourceAllocation) {
+ MplsLabelResourceAllocation mplsAllocation = (MplsLabelResourceAllocation) req;
+ if (!avail.contains(req)) {
+ throw new ResourceAllocationException(
+ PositionalParameterStringFormatter
+ .format("Unable to allocate MPLS label for link "
+ + "{} MPLS label is {}",
+ link,
+ mplsAllocation
+ .mplsLabel()
+ .toString()));
+ }
}
}
// all requests allocatable => add allocation
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 846fa75..4e9fe4f 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -87,6 +87,8 @@
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.intent.MplsIntent;
+import org.onosproject.net.intent.MplsPathIntent;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.OpticalPathIntent;
@@ -113,6 +115,9 @@
import org.onosproject.net.resource.LambdaResourceAllocation;
import org.onosproject.net.resource.LambdaResourceRequest;
import org.onosproject.net.resource.LinkResourceRequest;
+import org.onosproject.net.resource.MplsLabel;
+import org.onosproject.net.resource.MplsLabelResourceAllocation;
+import org.onosproject.net.resource.MplsLabelResourceRequest;
import org.onosproject.store.Timestamp;
import org.onosproject.store.service.BatchReadRequest;
import org.onosproject.store.service.BatchWriteRequest;
@@ -345,6 +350,14 @@
.register(WriteStatus.class)
.register(VersionedValue.class)
.register(DefaultGroupId.class)
+ .register(
+ MplsIntent.class,
+ MplsPathIntent.class,
+ MplsLabelResourceAllocation.class,
+ MplsLabelResourceRequest.class,
+ MplsLabel.class,
+ org.onlab.packet.MplsLabel.class
+ )
.build();
diff --git a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleGroupStoreTest.java b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleGroupStoreTest.java
index 33d7118..f890754 100644
--- a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleGroupStoreTest.java
+++ b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleGroupStoreTest.java
@@ -25,6 +25,7 @@
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.GroupId;
@@ -184,7 +185,7 @@
.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
.setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
.pushMpls()
- .setMpls(106);
+ .setMpls(MplsLabel.mplsLabel(106));
buckets.add(DefaultGroupBucket.createSelectGroupBucket(
tBuilder.build()));
}
@@ -244,7 +245,7 @@
.setEthDst(MacAddress.valueOf("00:00:00:00:00:03"))
.setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
.pushMpls()
- .setMpls(106);
+ .setMpls(MplsLabel.mplsLabel(106));
toAddBuckets.add(DefaultGroupBucket.createSelectGroupBucket(
tBuilder.build()));
}
@@ -347,7 +348,7 @@
.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
.setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
.pushMpls()
- .setMpls(106);
+ .setMpls(MplsLabel.mplsLabel(106));
buckets.add(DefaultGroupBucket.createSelectGroupBucket(
tBuilder.build()));
}