Committed by
Gerrit Code Review
[ONOS-4051] Path computation algorithm implementation (Coding & UT).
Change-Id: If94be2ba2a010a203003b7ce38289b516ab20f59
Showing
7 changed files
with
1776 additions
and
2 deletions
... | @@ -18,8 +18,10 @@ package org.onosproject.pce.pceservice; | ... | @@ -18,8 +18,10 @@ package org.onosproject.pce.pceservice; |
18 | import static com.google.common.base.Preconditions.checkNotNull; | 18 | import static com.google.common.base.Preconditions.checkNotNull; |
19 | import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS; | 19 | import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS; |
20 | 20 | ||
21 | +import java.util.Collections; | ||
21 | import java.util.Iterator; | 22 | import java.util.Iterator; |
22 | import java.util.List; | 23 | import java.util.List; |
24 | +import java.util.Set; | ||
23 | 25 | ||
24 | import org.apache.felix.scr.annotations.Activate; | 26 | import org.apache.felix.scr.annotations.Activate; |
25 | import org.apache.felix.scr.annotations.Component; | 27 | import org.apache.felix.scr.annotations.Component; |
... | @@ -34,8 +36,15 @@ import org.onosproject.incubator.net.tunnel.Tunnel; | ... | @@ -34,8 +36,15 @@ import org.onosproject.incubator.net.tunnel.Tunnel; |
34 | import org.onosproject.incubator.net.tunnel.TunnelId; | 36 | import org.onosproject.incubator.net.tunnel.TunnelId; |
35 | import org.onosproject.incubator.net.tunnel.TunnelService; | 37 | import org.onosproject.incubator.net.tunnel.TunnelService; |
36 | import org.onosproject.net.DeviceId; | 38 | import org.onosproject.net.DeviceId; |
39 | +import org.onosproject.net.Path; | ||
37 | import org.onosproject.net.intent.Constraint; | 40 | import org.onosproject.net.intent.Constraint; |
41 | +import org.onosproject.net.device.DeviceService; | ||
42 | +import org.onosproject.net.resource.ResourceService; | ||
43 | +import org.onosproject.net.topology.LinkWeight; | ||
44 | +import org.onosproject.net.topology.PathService; | ||
45 | +import org.onosproject.net.topology.TopologyEdge; | ||
38 | import org.onosproject.pce.pceservice.api.PceService; | 46 | import org.onosproject.pce.pceservice.api.PceService; |
47 | +import org.onosproject.pce.pceservice.constraint.CapabilityConstraint; | ||
39 | import org.onosproject.store.serializers.KryoNamespaces; | 48 | import org.onosproject.store.serializers.KryoNamespaces; |
40 | import org.onosproject.store.service.DistributedSet; | 49 | import org.onosproject.store.service.DistributedSet; |
41 | import org.onosproject.store.service.Serializer; | 50 | import org.onosproject.store.service.Serializer; |
... | @@ -43,6 +52,8 @@ import org.onosproject.store.service.StorageService; | ... | @@ -43,6 +52,8 @@ import org.onosproject.store.service.StorageService; |
43 | import org.slf4j.Logger; | 52 | import org.slf4j.Logger; |
44 | import org.slf4j.LoggerFactory; | 53 | import org.slf4j.LoggerFactory; |
45 | 54 | ||
55 | +import com.google.common.collect.ImmutableList; | ||
56 | + | ||
46 | /** | 57 | /** |
47 | * Implementation of PCE service. | 58 | * Implementation of PCE service. |
48 | */ | 59 | */ |
... | @@ -66,6 +77,15 @@ public class PceManager implements PceService { | ... | @@ -66,6 +77,15 @@ public class PceManager implements PceService { |
66 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 77 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
67 | protected StorageService storageService; | 78 | protected StorageService storageService; |
68 | 79 | ||
80 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
81 | + protected PathService pathService; | ||
82 | + | ||
83 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
84 | + protected ResourceService resourceService; | ||
85 | + | ||
86 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
87 | + protected DeviceService deviceService; | ||
88 | + | ||
69 | private ApplicationId appId; | 89 | private ApplicationId appId; |
70 | 90 | ||
71 | /** | 91 | /** |
... | @@ -92,6 +112,36 @@ public class PceManager implements PceService { | ... | @@ -92,6 +112,36 @@ public class PceManager implements PceService { |
92 | log.info("Stopped"); | 112 | log.info("Stopped"); |
93 | } | 113 | } |
94 | 114 | ||
115 | + /** | ||
116 | + * Returns an edge-weight capable of evaluating links on the basis of the | ||
117 | + * specified constraints. | ||
118 | + * | ||
119 | + * @param constraints path constraints | ||
120 | + * @return edge-weight function | ||
121 | + */ | ||
122 | + private LinkWeight weight(List<Constraint> constraints) { | ||
123 | + return new TeConstraintBasedLinkWeight(constraints); | ||
124 | + } | ||
125 | + | ||
126 | + /** | ||
127 | + * Computes a path between two devices. | ||
128 | + * | ||
129 | + * @param src ingress device | ||
130 | + * @param dst egress device | ||
131 | + * @param constraints path constraints | ||
132 | + * @return computed path based on constraints | ||
133 | + */ | ||
134 | + protected Set<Path> computePath(DeviceId src, DeviceId dst, List<Constraint> constraints) { | ||
135 | + if (pathService == null) { | ||
136 | + return null; | ||
137 | + } | ||
138 | + Set<Path> paths = pathService.getPaths(src, dst, weight(constraints)); | ||
139 | + if (!paths.isEmpty()) { | ||
140 | + return paths; | ||
141 | + } | ||
142 | + return null; | ||
143 | + } | ||
144 | + | ||
95 | //[TODO:] handle requests in queue | 145 | //[TODO:] handle requests in queue |
96 | @Override | 146 | @Override |
97 | public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints, | 147 | public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints, |
... | @@ -103,8 +153,8 @@ public class PceManager implements PceService { | ... | @@ -103,8 +153,8 @@ public class PceManager implements PceService { |
103 | checkNotNull(lspType); | 153 | checkNotNull(lspType); |
104 | 154 | ||
105 | // TODO: compute and setup path. | 155 | // TODO: compute and setup path. |
106 | - | 156 | + //TODO: gets the path based on constraints and creates a tunnel in network via tunnel manager |
107 | - return true; | 157 | + return computePath(src, dst, constraints) != null ? true : false; |
108 | } | 158 | } |
109 | 159 | ||
110 | 160 | ||
... | @@ -159,4 +209,44 @@ public class PceManager implements PceService { | ... | @@ -159,4 +209,44 @@ public class PceManager implements PceService { |
159 | return value; | 209 | return value; |
160 | } | 210 | } |
161 | 211 | ||
212 | + protected class TeConstraintBasedLinkWeight implements LinkWeight { | ||
213 | + | ||
214 | + private final List<Constraint> constraints; | ||
215 | + | ||
216 | + /** | ||
217 | + * Creates a new edge-weight function capable of evaluating links | ||
218 | + * on the basis of the specified constraints. | ||
219 | + * | ||
220 | + * @param constraints path constraints | ||
221 | + */ | ||
222 | + public TeConstraintBasedLinkWeight(List<Constraint> constraints) { | ||
223 | + if (constraints == null) { | ||
224 | + this.constraints = Collections.emptyList(); | ||
225 | + } else { | ||
226 | + this.constraints = ImmutableList.copyOf(constraints); | ||
227 | + } | ||
228 | + } | ||
229 | + | ||
230 | + @Override | ||
231 | + public double weight(TopologyEdge edge) { | ||
232 | + if (!constraints.iterator().hasNext()) { | ||
233 | + //Takes default cost/hopcount as 1 if no constraints specified | ||
234 | + return 1.0; | ||
235 | + } | ||
236 | + | ||
237 | + Iterator<Constraint> it = constraints.iterator(); | ||
238 | + double cost = 1; | ||
239 | + | ||
240 | + //If any constraint fails return -1 also value of cost returned from cost constraint can't be negative | ||
241 | + while (it.hasNext() && cost > 0) { | ||
242 | + Constraint constraint = it.next(); | ||
243 | + if (constraint instanceof CapabilityConstraint) { | ||
244 | + cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService) ? 1 : -1; | ||
245 | + } else { | ||
246 | + cost = constraint.cost(edge.link(), resourceService::isAvailable); | ||
247 | + } | ||
248 | + } | ||
249 | + return cost; | ||
250 | + } | ||
251 | + } | ||
162 | } | 252 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/CapabilityConstraint.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pce.pceservice.constraint; | ||
17 | + | ||
18 | +import org.onosproject.net.AnnotationKeys; | ||
19 | +import org.onosproject.net.Device; | ||
20 | +import org.onosproject.net.Link; | ||
21 | +import org.onosproject.net.device.DeviceService; | ||
22 | +import org.onosproject.net.intent.ResourceContext; | ||
23 | +import org.onosproject.net.intent.constraint.BooleanConstraint; | ||
24 | + | ||
25 | +import java.util.Objects; | ||
26 | + | ||
27 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
28 | + | ||
29 | +/** | ||
30 | + * Constraint that evaluates whether devices satisfies capability. | ||
31 | + */ | ||
32 | +public final class CapabilityConstraint extends BooleanConstraint { | ||
33 | + | ||
34 | + private final CapabilityType capabilityType; | ||
35 | + public static final String PCECC_CAPABILITY = "pceccCapability"; | ||
36 | + public static final String SR_CAPABILITY = "srCapability"; | ||
37 | + public static final String LABEL_STACK_CAPABILITY = "labelStackCapability"; | ||
38 | + public static final String LSRID = "lsrId"; | ||
39 | + public static final String L3 = "L3"; | ||
40 | + public static final String TRUE = "true"; | ||
41 | + | ||
42 | + /** | ||
43 | + * Represents about capability type. | ||
44 | + */ | ||
45 | + public enum CapabilityType { | ||
46 | + /** | ||
47 | + * Signifies that path is created via signaling mode. | ||
48 | + */ | ||
49 | + WITH_SIGNALLING(0), | ||
50 | + | ||
51 | + /** | ||
52 | + * Signifies that path is created via SR mode. | ||
53 | + */ | ||
54 | + SR_WITHOUT_SIGNALLING(1), | ||
55 | + | ||
56 | + /** | ||
57 | + * Signifies that path is created via without signaling and without SR mode. | ||
58 | + */ | ||
59 | + WITHOUT_SIGNALLING_AND_WITHOUT_SR(2); | ||
60 | + | ||
61 | + int value; | ||
62 | + | ||
63 | + /** | ||
64 | + * Assign val with the value as the capability type. | ||
65 | + * | ||
66 | + * @param val capability type | ||
67 | + */ | ||
68 | + CapabilityType(int val) { | ||
69 | + value = val; | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * Returns value of capability type. | ||
74 | + * | ||
75 | + * @return capability type | ||
76 | + */ | ||
77 | + public byte type() { | ||
78 | + return (byte) value; | ||
79 | + } | ||
80 | + } | ||
81 | + | ||
82 | + // Constructor for serialization | ||
83 | + private CapabilityConstraint() { | ||
84 | + capabilityType = null; | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * Creates a new capability constraint. | ||
89 | + * | ||
90 | + * @param capabilityType type of capability device supports | ||
91 | + */ | ||
92 | + public CapabilityConstraint(CapabilityType capabilityType) { | ||
93 | + this.capabilityType = capabilityType; | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * Creates a new capability constraint. | ||
98 | + * | ||
99 | + * @param capabilityType type of capability device supports | ||
100 | + * @return instance of CapabilityConstraint for specified capability type | ||
101 | + */ | ||
102 | + public static CapabilityConstraint of(CapabilityType capabilityType) { | ||
103 | + return new CapabilityConstraint(capabilityType); | ||
104 | + } | ||
105 | + | ||
106 | + /** | ||
107 | + * Obtains type of capability. | ||
108 | + * | ||
109 | + * @return type of capability | ||
110 | + */ | ||
111 | + public CapabilityType capabilityType() { | ||
112 | + return capabilityType; | ||
113 | + } | ||
114 | + | ||
115 | + /** | ||
116 | + * Validates the link based on capability constraint. | ||
117 | + * | ||
118 | + * @param link to validate source and destination based on capability constraint | ||
119 | + * @param deviceService instance of DeviceService | ||
120 | + * @return true if link satisfies capability constraint otherwise false | ||
121 | + */ | ||
122 | + public boolean isValidLink(Link link, DeviceService deviceService) { | ||
123 | + if (deviceService == null) { | ||
124 | + return false; | ||
125 | + } | ||
126 | + | ||
127 | + Device srcDevice = deviceService.getDevice(link.src().deviceId()); | ||
128 | + Device dstDevice = deviceService.getDevice(link.dst().deviceId()); | ||
129 | + | ||
130 | + //TODO: Usage of annotations are for transient solution. In future will be replaces with the | ||
131 | + // network config service / Projection model. | ||
132 | + // L3 device | ||
133 | + if (srcDevice == null | ||
134 | + || dstDevice == null | ||
135 | + || srcDevice.annotations().value(AnnotationKeys.TYPE) == null | ||
136 | + || dstDevice.annotations().value(AnnotationKeys.TYPE) == null | ||
137 | + || !srcDevice.annotations().value(AnnotationKeys.TYPE).equals(L3) | ||
138 | + || !dstDevice.annotations().value(AnnotationKeys.TYPE).equals(L3)) { | ||
139 | + return false; | ||
140 | + } | ||
141 | + | ||
142 | + String scrLsrId = srcDevice.annotations().value(LSRID); | ||
143 | + String dstLsrId = dstDevice.annotations().value(LSRID); | ||
144 | + | ||
145 | + Device srcCapDevice = null; | ||
146 | + Device dstCapDevice = null; | ||
147 | + | ||
148 | + // Get Capability device | ||
149 | + Iterable<Device> devices = deviceService.getAvailableDevices(); | ||
150 | + for (Device dev : devices) { | ||
151 | + if (dev.annotations().value(LSRID).equals(scrLsrId)) { | ||
152 | + srcCapDevice = dev; | ||
153 | + } else if (dev.annotations().value(LSRID).equals(dstLsrId)) { | ||
154 | + dstCapDevice = dev; | ||
155 | + } | ||
156 | + } | ||
157 | + | ||
158 | + if (srcCapDevice == null || dstCapDevice == null) { | ||
159 | + return false; | ||
160 | + } | ||
161 | + | ||
162 | + switch (capabilityType) { | ||
163 | + case WITH_SIGNALLING: | ||
164 | + return true; | ||
165 | + case WITHOUT_SIGNALLING_AND_WITHOUT_SR: | ||
166 | + if (srcCapDevice.annotations().value(PCECC_CAPABILITY) != null | ||
167 | + && dstCapDevice.annotations().value(PCECC_CAPABILITY) != null) { | ||
168 | + return srcCapDevice.annotations().value(PCECC_CAPABILITY).equals(TRUE) | ||
169 | + && dstCapDevice.annotations().value(PCECC_CAPABILITY).equals(TRUE); | ||
170 | + } | ||
171 | + return false; | ||
172 | + case SR_WITHOUT_SIGNALLING: | ||
173 | + if (srcCapDevice.annotations().value(LABEL_STACK_CAPABILITY) != null | ||
174 | + && dstCapDevice.annotations().value(LABEL_STACK_CAPABILITY) != null | ||
175 | + && srcCapDevice.annotations().value(SR_CAPABILITY) != null | ||
176 | + && dstCapDevice.annotations().value(SR_CAPABILITY) != null) { | ||
177 | + return srcCapDevice.annotations().value(LABEL_STACK_CAPABILITY).equals(TRUE) | ||
178 | + && dstCapDevice.annotations().value(LABEL_STACK_CAPABILITY).equals(TRUE) | ||
179 | + && srcCapDevice.annotations().value(SR_CAPABILITY).equals(TRUE) | ||
180 | + && dstCapDevice.annotations().value(SR_CAPABILITY).equals(TRUE); | ||
181 | + } | ||
182 | + return false; | ||
183 | + default: | ||
184 | + return false; | ||
185 | + } | ||
186 | + } | ||
187 | + | ||
188 | + @Override | ||
189 | + public boolean isValid(Link link, ResourceContext context) { | ||
190 | + return false; | ||
191 | + //Do nothing instead using isValidLink needs device service to validate link | ||
192 | + } | ||
193 | + | ||
194 | + @Override | ||
195 | + public int hashCode() { | ||
196 | + return Objects.hash(capabilityType); | ||
197 | + } | ||
198 | + | ||
199 | + @Override | ||
200 | + public boolean equals(Object obj) { | ||
201 | + if (this == obj) { | ||
202 | + return true; | ||
203 | + } | ||
204 | + | ||
205 | + if (obj instanceof CapabilityConstraint) { | ||
206 | + CapabilityConstraint other = (CapabilityConstraint) obj; | ||
207 | + return Objects.equals(this.capabilityType, other.capabilityType); | ||
208 | + } | ||
209 | + | ||
210 | + return false; | ||
211 | + } | ||
212 | + | ||
213 | + @Override | ||
214 | + public String toString() { | ||
215 | + return toStringHelper(this) | ||
216 | + .add("capabilityType", capabilityType) | ||
217 | + .toString(); | ||
218 | + } | ||
219 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pce.pceservice.constraint; | ||
17 | + | ||
18 | +import org.onosproject.net.Link; | ||
19 | +import org.onosproject.net.Path; | ||
20 | +import org.onosproject.net.intent.ResourceContext; | ||
21 | +import org.onosproject.net.intent.Constraint; | ||
22 | + | ||
23 | +import java.util.Objects; | ||
24 | + | ||
25 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
26 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
27 | + | ||
28 | +/** | ||
29 | + * Constraint that evaluates whether cost for a link is available, if yes return cost for that link. | ||
30 | + */ | ||
31 | +public final class CostConstraint implements Constraint { | ||
32 | + | ||
33 | + /** | ||
34 | + * Represents about cost types. | ||
35 | + */ | ||
36 | + public enum Type { | ||
37 | + /** | ||
38 | + * Signifies that cost is IGP cost. | ||
39 | + */ | ||
40 | + COST(1), | ||
41 | + | ||
42 | + /** | ||
43 | + * Signifies that cost is TE cost. | ||
44 | + */ | ||
45 | + TE_COST(2); | ||
46 | + | ||
47 | + int value; | ||
48 | + | ||
49 | + /** | ||
50 | + * Assign val with the value as the Cost type. | ||
51 | + * | ||
52 | + * @param val Cost type | ||
53 | + */ | ||
54 | + Type(int val) { | ||
55 | + value = val; | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
59 | + * Returns value of Cost type. | ||
60 | + * | ||
61 | + * @return Cost type | ||
62 | + */ | ||
63 | + public byte type() { | ||
64 | + return (byte) value; | ||
65 | + } | ||
66 | + } | ||
67 | + | ||
68 | + private final Type type; | ||
69 | + public static final String TE_COST = "teCost"; | ||
70 | + public static final String COST = "cost"; | ||
71 | + | ||
72 | + // Constructor for serialization | ||
73 | + private CostConstraint() { | ||
74 | + this.type = null; | ||
75 | + } | ||
76 | + | ||
77 | + /** | ||
78 | + * Creates a new cost constraint. | ||
79 | + * | ||
80 | + * @param type of a link | ||
81 | + */ | ||
82 | + public CostConstraint(Type type) { | ||
83 | + this.type = checkNotNull(type, "Type cannot be null"); | ||
84 | + } | ||
85 | + | ||
86 | + /** | ||
87 | + * Creates new CostConstraint with specified cost type. | ||
88 | + * | ||
89 | + * @param type of cost | ||
90 | + * @return instance of CostConstraint | ||
91 | + */ | ||
92 | + public static CostConstraint of(Type type) { | ||
93 | + return new CostConstraint(type); | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * Returns the type of a cost specified in a constraint. | ||
98 | + * | ||
99 | + * @return required cost type | ||
100 | + */ | ||
101 | + public Type type() { | ||
102 | + return type; | ||
103 | + } | ||
104 | + | ||
105 | + @Override | ||
106 | + public int hashCode() { | ||
107 | + return Objects.hash(type); | ||
108 | + } | ||
109 | + | ||
110 | + @Override | ||
111 | + public boolean equals(Object obj) { | ||
112 | + if (this == obj) { | ||
113 | + return true; | ||
114 | + } | ||
115 | + | ||
116 | + if (obj instanceof CostConstraint) { | ||
117 | + CostConstraint other = (CostConstraint) obj; | ||
118 | + return Objects.equals(this.type, other.type); | ||
119 | + } | ||
120 | + | ||
121 | + return false; | ||
122 | + } | ||
123 | + | ||
124 | + @Override | ||
125 | + public String toString() { | ||
126 | + return toStringHelper(this) | ||
127 | + .add("type", type) | ||
128 | + .toString(); | ||
129 | + } | ||
130 | + | ||
131 | + @Override | ||
132 | + public double cost(Link link, ResourceContext context) { | ||
133 | + //TODO: Usage of annotations are for transient solution. In future will be replaces with the | ||
134 | + // network config service / Projection model. | ||
135 | + switch (type) { | ||
136 | + case COST: | ||
137 | + if (link.annotations().value(COST) != null) { | ||
138 | + return Double.parseDouble(link.annotations().value(COST)); | ||
139 | + } | ||
140 | + | ||
141 | + //If cost annotations absent return -1[It is not L3 device] | ||
142 | + return -1; | ||
143 | + case TE_COST: | ||
144 | + if (link.annotations().value(TE_COST) != null) { | ||
145 | + return Double.parseDouble(link.annotations().value(TE_COST)); | ||
146 | + } | ||
147 | + | ||
148 | + //If TE cost annotations absent return -1[It is not L3 device] | ||
149 | + return -1; | ||
150 | + default: | ||
151 | + return -1; | ||
152 | + } | ||
153 | + } | ||
154 | + | ||
155 | + @Override | ||
156 | + public boolean validate(Path path, ResourceContext context) { | ||
157 | + // TODO Auto-generated method stub | ||
158 | + return false; | ||
159 | + } | ||
160 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/SharedBandwidthConstraint.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pce.pceservice.constraint; | ||
17 | + | ||
18 | +import org.onlab.util.Bandwidth; | ||
19 | +import org.onosproject.net.Link; | ||
20 | +import org.onosproject.net.intent.ResourceContext; | ||
21 | +import org.onosproject.net.intent.constraint.BooleanConstraint; | ||
22 | +import org.onosproject.net.resource.Resources; | ||
23 | + | ||
24 | +import java.util.List; | ||
25 | +import java.util.Objects; | ||
26 | +import java.util.stream.Stream; | ||
27 | + | ||
28 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
29 | + | ||
30 | +/** | ||
31 | + * Constraint that evaluates whether links satisfies sharedbandwidth request. | ||
32 | + */ | ||
33 | +public final class SharedBandwidthConstraint extends BooleanConstraint { | ||
34 | + | ||
35 | + private final List<Link> links; | ||
36 | + private final Bandwidth sharedBwValue; | ||
37 | + private final Bandwidth requestBwValue; | ||
38 | + //temporary variable declared to hold changed bandwidth value | ||
39 | + private Bandwidth changedBwValue; | ||
40 | + | ||
41 | + // Constructor for serialization | ||
42 | + private SharedBandwidthConstraint() { | ||
43 | + links = null; | ||
44 | + sharedBwValue = null; | ||
45 | + requestBwValue = null; | ||
46 | + } | ||
47 | + | ||
48 | + /** | ||
49 | + * Creates a new SharedBandwidth constraint. | ||
50 | + * | ||
51 | + * @param links shared links | ||
52 | + * @param sharedBwValue shared bandwidth of the links | ||
53 | + * @param requestBwValue requested bandwidth value | ||
54 | + */ | ||
55 | + public SharedBandwidthConstraint(List<Link> links, Bandwidth sharedBwValue, Bandwidth requestBwValue) { | ||
56 | + this.links = links; | ||
57 | + this.sharedBwValue = sharedBwValue; | ||
58 | + this.requestBwValue = requestBwValue; | ||
59 | + } | ||
60 | + | ||
61 | + /** | ||
62 | + * Creates a new SharedBandwidth constraint. | ||
63 | + * | ||
64 | + * @param links shared links | ||
65 | + * @param sharedBwValue shared bandwidth of the links | ||
66 | + * @param requestBwValue requested bandwidth value | ||
67 | + * @return SharedBandwidth instance | ||
68 | + */ | ||
69 | + public static SharedBandwidthConstraint of(List<Link> links, Bandwidth sharedBwValue, Bandwidth requestBwValue) { | ||
70 | + return new SharedBandwidthConstraint(links, sharedBwValue, requestBwValue); | ||
71 | + } | ||
72 | + | ||
73 | + /** | ||
74 | + * Obtains shared links. | ||
75 | + * | ||
76 | + * @return shared links | ||
77 | + */ | ||
78 | + public List<Link> links() { | ||
79 | + return links; | ||
80 | + } | ||
81 | + | ||
82 | + /** | ||
83 | + * Obtains shared bandwidth of the links. | ||
84 | + * | ||
85 | + * @return shared bandwidth | ||
86 | + */ | ||
87 | + public Bandwidth sharedBwValue() { | ||
88 | + return sharedBwValue; | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * Obtains requested bandwidth value. | ||
93 | + * | ||
94 | + * @return requested bandwidth value | ||
95 | + */ | ||
96 | + public Bandwidth requestBwValue() { | ||
97 | + return requestBwValue; | ||
98 | + } | ||
99 | + | ||
100 | + @Override | ||
101 | + public boolean isValid(Link link, ResourceContext context) { | ||
102 | + changedBwValue = requestBwValue; | ||
103 | + if (links.contains(link)) { | ||
104 | + changedBwValue = requestBwValue.isGreaterThan(sharedBwValue) ? requestBwValue.subtract(sharedBwValue) | ||
105 | + : Bandwidth.bps(0); | ||
106 | + } | ||
107 | + | ||
108 | + return Stream | ||
109 | + .of(link.src(), link.dst()) | ||
110 | + .map(cp -> Resources.continuous(cp.deviceId(), cp.port(), Bandwidth.class).resource( | ||
111 | + changedBwValue.bps())).allMatch(context::isAvailable); | ||
112 | + } | ||
113 | + | ||
114 | + @Override | ||
115 | + public int hashCode() { | ||
116 | + return Objects.hash(requestBwValue, sharedBwValue, links); | ||
117 | + } | ||
118 | + | ||
119 | + @Override | ||
120 | + public boolean equals(Object obj) { | ||
121 | + if (this == obj) { | ||
122 | + return true; | ||
123 | + } | ||
124 | + | ||
125 | + if (obj instanceof SharedBandwidthConstraint) { | ||
126 | + SharedBandwidthConstraint other = (SharedBandwidthConstraint) obj; | ||
127 | + return Objects.equals(this.requestBwValue, other.requestBwValue) | ||
128 | + && Objects.equals(this.sharedBwValue, other.sharedBwValue) | ||
129 | + && Objects.equals(this.links, other.links); | ||
130 | + } | ||
131 | + | ||
132 | + return false; | ||
133 | + } | ||
134 | + | ||
135 | + @Override | ||
136 | + public String toString() { | ||
137 | + return toStringHelper(this) | ||
138 | + .add("requestBwValue", requestBwValue) | ||
139 | + .add("sharedBwValue", sharedBwValue) | ||
140 | + .add("links", links) | ||
141 | + .toString(); | ||
142 | + } | ||
143 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/** | ||
18 | + * Constraints for path computation for PCE service. | ||
19 | + */ | ||
20 | +package org.onosproject.pce.pceservice.constraint; |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pce.pceservice; | ||
17 | + | ||
18 | +import org.junit.After; | ||
19 | +import org.junit.Before; | ||
20 | +import org.junit.Test; | ||
21 | +import org.onlab.graph.AbstractGraphPathSearch; | ||
22 | +import org.onlab.graph.AdjacencyListsGraph; | ||
23 | +import org.onlab.graph.DijkstraGraphSearch; | ||
24 | +import org.onlab.graph.Graph; | ||
25 | +import org.onlab.graph.GraphPathSearch; | ||
26 | +import org.onlab.packet.ChassisId; | ||
27 | +import org.onlab.util.Bandwidth; | ||
28 | +import org.onlab.util.Tools; | ||
29 | +import org.onosproject.net.AnnotationKeys; | ||
30 | +import org.onosproject.net.ConnectPoint; | ||
31 | +import org.onosproject.net.DefaultAnnotations; | ||
32 | +import org.onosproject.net.DefaultDevice; | ||
33 | +import org.onosproject.net.DefaultLink; | ||
34 | +import org.onosproject.net.DefaultPath; | ||
35 | +import org.onosproject.net.Device; | ||
36 | +import org.onosproject.net.DeviceId; | ||
37 | +import org.onosproject.net.Link; | ||
38 | +import org.onosproject.net.Path; | ||
39 | +import org.onosproject.net.PortNumber; | ||
40 | +import org.onosproject.net.intent.Constraint; | ||
41 | +import org.onosproject.net.intent.IntentId; | ||
42 | +import org.onosproject.net.Device.Type; | ||
43 | +import org.onosproject.net.intent.constraint.BandwidthConstraint; | ||
44 | +import org.onosproject.net.device.DeviceServiceAdapter; | ||
45 | +import org.onosproject.net.resource.ContinuousResource; | ||
46 | +import org.onosproject.net.resource.ContinuousResourceId; | ||
47 | +import org.onosproject.net.resource.DiscreteResource; | ||
48 | +import org.onosproject.net.resource.DiscreteResourceId; | ||
49 | +import org.onosproject.net.resource.Resource; | ||
50 | +import org.onosproject.net.resource.ResourceAllocation; | ||
51 | +import org.onosproject.net.resource.ResourceConsumer; | ||
52 | +import org.onosproject.net.resource.ResourceId; | ||
53 | +import org.onosproject.net.resource.Resources; | ||
54 | +import org.onosproject.net.provider.ProviderId; | ||
55 | +import org.onosproject.net.topology.DefaultTopologyEdge; | ||
56 | +import org.onosproject.net.topology.DefaultTopologyVertex; | ||
57 | +import org.onosproject.net.topology.LinkWeight; | ||
58 | +import org.onosproject.net.topology.TopologyEdge; | ||
59 | +import org.onosproject.net.topology.TopologyVertex; | ||
60 | +import org.onosproject.pce.pceservice.constraint.CapabilityConstraint; | ||
61 | +import org.onosproject.pce.pceservice.constraint.CostConstraint; | ||
62 | +import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint; | ||
63 | + | ||
64 | +import com.google.common.collect.ImmutableList; | ||
65 | +import com.google.common.collect.ImmutableSet; | ||
66 | + | ||
67 | +import java.util.Collections; | ||
68 | +import java.util.HashMap; | ||
69 | +import java.util.HashSet; | ||
70 | +import java.util.Iterator; | ||
71 | +import java.util.LinkedList; | ||
72 | +import java.util.List; | ||
73 | +import java.util.Map; | ||
74 | +import java.util.Optional; | ||
75 | +import java.util.Set; | ||
76 | +import java.util.stream.Collectors; | ||
77 | + | ||
78 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
79 | +import static org.hamcrest.core.Is.is; | ||
80 | +import static org.onlab.graph.GraphPathSearch.ALL_PATHS; | ||
81 | +import static org.onosproject.core.CoreService.CORE_PROVIDER_ID; | ||
82 | +import static com.google.common.collect.ImmutableSet.of; | ||
83 | +import static org.onosproject.net.resource.Resources.continuous; | ||
84 | +import static org.onosproject.net.Link.Type.DIRECT; | ||
85 | +import static org.onosproject.net.Link.State.ACTIVE; | ||
86 | +import static org.onosproject.net.DeviceId.deviceId; | ||
87 | +import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST; | ||
88 | +import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.TE_COST; | ||
89 | + | ||
90 | +/** | ||
91 | + * Test for CSPF path computation. | ||
92 | + */ | ||
93 | +public class PathComputationTest { | ||
94 | + | ||
95 | + private final MockPathResourceService resourceService = new MockPathResourceService(); | ||
96 | + private final MockDeviceService deviceService = new MockDeviceService(); | ||
97 | + private PceManager pceManager = new PceManager(); | ||
98 | + public static ProviderId providerId = new ProviderId("pce", "foo"); | ||
99 | + private static final String DEVICE1 = "D001"; | ||
100 | + private static final String DEVICE2 = "D002"; | ||
101 | + private static final String DEVICE3 = "D003"; | ||
102 | + private static final String DEVICE4 = "D004"; | ||
103 | + private static final String DEVICE5 = "D005"; | ||
104 | + public static final String PCEPDEVICE1 = "PD001"; | ||
105 | + public static final String PCEPDEVICE2 = "PD002"; | ||
106 | + public static final String PCEPDEVICE3 = "PD003"; | ||
107 | + public static final String PCEPDEVICE4 = "PD004"; | ||
108 | + private static final TopologyVertex D1 = new DefaultTopologyVertex(DeviceId.deviceId("D001")); | ||
109 | + private static final TopologyVertex D2 = new DefaultTopologyVertex(DeviceId.deviceId("D002")); | ||
110 | + private static final TopologyVertex D3 = new DefaultTopologyVertex(DeviceId.deviceId("D003")); | ||
111 | + private static final TopologyVertex D4 = new DefaultTopologyVertex(DeviceId.deviceId("D004")); | ||
112 | + private static final TopologyVertex D5 = new DefaultTopologyVertex(DeviceId.deviceId("D005")); | ||
113 | + private static final String ANNOTATION_COST = "cost"; | ||
114 | + private static final String ANNOTATION_TE_COST = "teCost"; | ||
115 | + private static final String UNKNOWN = "unknown"; | ||
116 | + public static final String LSRID = "lsrId"; | ||
117 | + public static final String L3 = "L3"; | ||
118 | + public static final String PCECC_CAPABILITY = "pceccCapability"; | ||
119 | + public static final String SR_CAPABILITY = "srCapability"; | ||
120 | + public static final String LABEL_STACK_CAPABILITY = "labelStackCapability"; | ||
121 | + | ||
122 | + @Before | ||
123 | + public void startUp() { | ||
124 | + pceManager.resourceService = resourceService; | ||
125 | + pceManager.deviceService = deviceService; | ||
126 | + } | ||
127 | + | ||
128 | + /** | ||
129 | + * Selects path computation algorithm. | ||
130 | + * | ||
131 | + * @return graph path search algorithm | ||
132 | + */ | ||
133 | + private AbstractGraphPathSearch<TopologyVertex, TopologyEdge> graphSearch() { | ||
134 | + return new DijkstraGraphSearch<>(); | ||
135 | + } | ||
136 | + | ||
137 | + /** | ||
138 | + * Returns link for two devices. | ||
139 | + * | ||
140 | + * @param device source device | ||
141 | + * @param port source port | ||
142 | + * @param device2 destination device | ||
143 | + * @param port2 destination port | ||
144 | + * @return link | ||
145 | + */ | ||
146 | + private Link addLink(String device, long port, String device2, long port2, boolean setCost, int value) { | ||
147 | + ConnectPoint src = new ConnectPoint(DeviceId.deviceId(device), PortNumber.portNumber(port)); | ||
148 | + ConnectPoint dst = new ConnectPoint(DeviceId.deviceId(device2), PortNumber.portNumber(port2)); | ||
149 | + Link curLink; | ||
150 | + DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder(); | ||
151 | + if (setCost) { | ||
152 | + annotationBuilder.set(ANNOTATION_COST, String.valueOf(value)); | ||
153 | + } else { | ||
154 | + annotationBuilder.set(ANNOTATION_TE_COST, String.valueOf(value)); | ||
155 | + } | ||
156 | + | ||
157 | + //TODO:If cost not set cost : default value case | ||
158 | + curLink = DefaultLink.builder().src(src).dst(dst).state(ACTIVE).type(DIRECT) | ||
159 | + .providerId(PathComputationTest.providerId).annotations(annotationBuilder.build()).build(); | ||
160 | + return curLink; | ||
161 | + } | ||
162 | + | ||
163 | + @After | ||
164 | + public void tearDown() { | ||
165 | + pceManager.resourceService = null; | ||
166 | + pceManager.deviceService = null; | ||
167 | + } | ||
168 | + | ||
169 | + /** | ||
170 | + * Returns an edge-weight capable of evaluating links on the basis of the | ||
171 | + * specified constraints. | ||
172 | + * | ||
173 | + * @param constraints path constraints | ||
174 | + * @return edge-weight function | ||
175 | + */ | ||
176 | + private LinkWeight weight(List<Constraint> constraints) { | ||
177 | + return new MockTeConstraintBasedLinkWeight(constraints); | ||
178 | + } | ||
179 | + | ||
180 | + private Set<Path> computePath(Link link1, Link link2, Link link3, Link link4, List<Constraint> constraints) { | ||
181 | + Graph<TopologyVertex, TopologyEdge> graph = new AdjacencyListsGraph<>(of(D1, D2, D3, D4), | ||
182 | + of(new DefaultTopologyEdge(D1, D2, link1), | ||
183 | + new DefaultTopologyEdge(D2, D4, link2), | ||
184 | + new DefaultTopologyEdge(D1, D3, link3), | ||
185 | + new DefaultTopologyEdge(D3, D4, link4))); | ||
186 | + | ||
187 | + GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = | ||
188 | + graphSearch().search(graph, D1, D4, weight(constraints), ALL_PATHS); | ||
189 | + ImmutableSet.Builder<Path> builder = ImmutableSet.builder(); | ||
190 | + for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { | ||
191 | + builder.add(networkPath(path)); | ||
192 | + } | ||
193 | + return builder.build(); | ||
194 | + } | ||
195 | + | ||
196 | + private class MockDeviceService extends DeviceServiceAdapter { | ||
197 | + List<Device> devices = new LinkedList<>(); | ||
198 | + | ||
199 | + private void addDevice(Device dev) { | ||
200 | + devices.add(dev); | ||
201 | + } | ||
202 | + | ||
203 | + @Override | ||
204 | + public Device getDevice(DeviceId deviceId) { | ||
205 | + for (Device dev : devices) { | ||
206 | + if (dev.id().equals(deviceId)) { | ||
207 | + return dev; | ||
208 | + } | ||
209 | + } | ||
210 | + return null; | ||
211 | + } | ||
212 | + | ||
213 | + @Override | ||
214 | + public Iterable<Device> getAvailableDevices() { | ||
215 | + return devices; | ||
216 | + } | ||
217 | + } | ||
218 | + | ||
219 | + private class MockTeConstraintBasedLinkWeight implements LinkWeight { | ||
220 | + | ||
221 | + private final List<Constraint> constraints; | ||
222 | + | ||
223 | + /** | ||
224 | + * Creates a new edge-weight function capable of evaluating links | ||
225 | + * on the basis of the specified constraints. | ||
226 | + * | ||
227 | + * @param constraints path constraints | ||
228 | + */ | ||
229 | + MockTeConstraintBasedLinkWeight(List<Constraint> constraints) { | ||
230 | + if (constraints == null) { | ||
231 | + this.constraints = Collections.emptyList(); | ||
232 | + } else { | ||
233 | + this.constraints = ImmutableList.copyOf(constraints); | ||
234 | + } | ||
235 | + } | ||
236 | + | ||
237 | + public double weight(TopologyEdge edge) { | ||
238 | + if (!constraints.iterator().hasNext()) { | ||
239 | + //Takes default cost/hopcount as 1 if no constraints specified | ||
240 | + return 1.0; | ||
241 | + } | ||
242 | + | ||
243 | + Iterator<Constraint> it = constraints.iterator(); | ||
244 | + double cost = 1; | ||
245 | + | ||
246 | + //If any constraint fails return -1 also value of cost returned from cost constraint can't be negative | ||
247 | + while (it.hasNext() && cost > 0) { | ||
248 | + Constraint constraint = it.next(); | ||
249 | + if (constraint instanceof CapabilityConstraint) { | ||
250 | + cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService) ? 1 : -1; | ||
251 | + } else { | ||
252 | + cost = constraint.cost(edge.link(), resourceService::isAvailable); | ||
253 | + } | ||
254 | + } | ||
255 | + return cost; | ||
256 | + } | ||
257 | + } | ||
258 | + | ||
259 | + private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) { | ||
260 | + List<Link> links = path.edges().stream().map(TopologyEdge::link).collect(Collectors.toList()); | ||
261 | + return new DefaultPath(CORE_PROVIDER_ID, links, path.cost()); | ||
262 | + } | ||
263 | + | ||
264 | + /** | ||
265 | + * Test Resource service for path computation. | ||
266 | + */ | ||
267 | + private class MockPathResourceService extends ResourceServiceAdapter { | ||
268 | + private final Map<Resource, ResourceConsumer> assignment = new HashMap<>(); | ||
269 | + private Map<ResourceId, List<ResourceAllocation>> resourcesAllocations = new HashMap<>(); | ||
270 | + | ||
271 | + @Override | ||
272 | + public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<Resource> resources) { | ||
273 | + for (Resource resource: resources) { | ||
274 | + if (resource instanceof ContinuousResource) { | ||
275 | + List<ResourceAllocation> allocs = new LinkedList<>(); | ||
276 | + allocs.add(new ResourceAllocation(resource, consumer)); | ||
277 | + resourcesAllocations.put(resource.id(), allocs); | ||
278 | + } | ||
279 | + } | ||
280 | + return resources.stream() | ||
281 | + .map(x -> new ResourceAllocation(x, consumer)) | ||
282 | + .collect(Collectors.toList()); | ||
283 | + } | ||
284 | + | ||
285 | + @Override | ||
286 | + public List<ResourceAllocation> getResourceAllocations(ResourceId id) { | ||
287 | + if (id instanceof ContinuousResourceId) { | ||
288 | + return resourcesAllocations.get(id); | ||
289 | + } | ||
290 | + DiscreteResource discrete = Resources.discrete((DiscreteResourceId) id).resource(); | ||
291 | + return Optional.ofNullable(assignment.get(discrete)) | ||
292 | + .map(x -> ImmutableList.of(new ResourceAllocation(discrete, x))) | ||
293 | + .orElse(ImmutableList.of()); | ||
294 | + } | ||
295 | + | ||
296 | + @Override | ||
297 | + public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) { | ||
298 | + return getAvailableResources(parent).stream() | ||
299 | + .filter(x -> x.isTypeOf(cls)) | ||
300 | + .collect(Collectors.toSet()); | ||
301 | + } | ||
302 | + | ||
303 | + @Override | ||
304 | + public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) { | ||
305 | + return getAvailableResources(parent).stream() | ||
306 | + .filter(x -> x.isTypeOf(cls)) | ||
307 | + .flatMap(x -> Tools.stream(x.valueAs(cls))) | ||
308 | + .collect(Collectors.toSet()); | ||
309 | + } | ||
310 | + | ||
311 | + @Override | ||
312 | + public boolean isAvailable(Resource resource) { | ||
313 | + if (resource instanceof DiscreteResource) { | ||
314 | + return true; | ||
315 | + } | ||
316 | + | ||
317 | + if (resource instanceof ContinuousResource) { | ||
318 | + List<ResourceAllocation> resalloc = resourcesAllocations.get(resource.id()); | ||
319 | + | ||
320 | + if ((resalloc != null) && (!resalloc.isEmpty())) { | ||
321 | + if (((ContinuousResource) resalloc.iterator().next().resource()).value() | ||
322 | + >= ((ContinuousResource) resource).value()) { | ||
323 | + return true; | ||
324 | + } | ||
325 | + } | ||
326 | + } | ||
327 | + return false; | ||
328 | + } | ||
329 | + } | ||
330 | + | ||
331 | + /** | ||
332 | + * All links with different costs with L1-L2 as least cost path. | ||
333 | + */ | ||
334 | + @Test | ||
335 | + public void testpathComputationCase1() { | ||
336 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
337 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20); | ||
338 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100); | ||
339 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 50); | ||
340 | + | ||
341 | + CostConstraint costConst = CostConstraint.of(COST); | ||
342 | + List<Constraint> constraints = new LinkedList<>(); | ||
343 | + constraints.add(costConst); | ||
344 | + | ||
345 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
346 | + | ||
347 | + List<Link> links = new LinkedList<>(); | ||
348 | + | ||
349 | + links.add(link1); | ||
350 | + links.add(link2); | ||
351 | + | ||
352 | + assertThat(paths.iterator().next().links(), is(links)); | ||
353 | + assertThat(paths.iterator().next().cost(), is((double) 70)); | ||
354 | + } | ||
355 | + | ||
356 | + /** | ||
357 | + * Links with same cost 100 except link3. | ||
358 | + */ | ||
359 | + @Test | ||
360 | + public void testpathComputationCase2() { | ||
361 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 100); | ||
362 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 100); | ||
363 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 1000); | ||
364 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 100); | ||
365 | + | ||
366 | + CostConstraint costConst = CostConstraint.of(COST); | ||
367 | + List<Constraint> constraints = new LinkedList<>(); | ||
368 | + constraints.add(costConst); | ||
369 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
370 | + | ||
371 | + List<Link> links = new LinkedList<>(); | ||
372 | + links.add(link1); | ||
373 | + links.add(link2); | ||
374 | + | ||
375 | + assertThat(paths.iterator().next().links(), is(links)); | ||
376 | + assertThat(paths.iterator().next().cost(), is((double) 200)); | ||
377 | + } | ||
378 | + | ||
379 | + /** | ||
380 | + * Path which satisfy bandwidth as a constraint with 10bps. | ||
381 | + */ | ||
382 | + @Test | ||
383 | + public void testpathComputationCase3() { | ||
384 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
385 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20); | ||
386 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100); | ||
387 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 50); | ||
388 | + | ||
389 | + List<Resource> resources = new LinkedList<>(); | ||
390 | + | ||
391 | + resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class) | ||
392 | + .resource(50)); | ||
393 | + resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class) | ||
394 | + .resource(50)); | ||
395 | + resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class) | ||
396 | + .resource(100)); | ||
397 | + resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class) | ||
398 | + .resource(100)); | ||
399 | + | ||
400 | + resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class) | ||
401 | + .resource(50)); | ||
402 | + resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class) | ||
403 | + .resource(50)); | ||
404 | + resources.add(continuous(link3.dst().deviceId(), link3.src().port(), Bandwidth.class) | ||
405 | + .resource(100)); | ||
406 | + resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class) | ||
407 | + .resource(100)); | ||
408 | + | ||
409 | + resourceService.allocate(IntentId.valueOf(70), resources); | ||
410 | + | ||
411 | + BandwidthConstraint bandwidthConst = new BandwidthConstraint(Bandwidth.bps(10.0)); | ||
412 | + | ||
413 | + List<Constraint> constraints = new LinkedList<>(); | ||
414 | + constraints.add(bandwidthConst); | ||
415 | + | ||
416 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
417 | + | ||
418 | + assertThat(paths.iterator().next().cost(), is((double) 2)); | ||
419 | + } | ||
420 | + | ||
421 | + /** | ||
422 | + * Path which satisfy bandwidth as a constraint with 60bps. | ||
423 | + */ | ||
424 | + @Test | ||
425 | + public void testpathComputationCase4() { | ||
426 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
427 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 50); | ||
428 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100); | ||
429 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 100); | ||
430 | + | ||
431 | + List<Resource> resources = new LinkedList<>(); | ||
432 | + | ||
433 | + resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50)); | ||
434 | + resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50)); | ||
435 | + resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100)); | ||
436 | + resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100)); | ||
437 | + | ||
438 | + resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50)); | ||
439 | + resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50)); | ||
440 | + resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100)); | ||
441 | + resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100)); | ||
442 | + | ||
443 | + resourceService.allocate(IntentId.valueOf(70), resources); | ||
444 | + | ||
445 | + BandwidthConstraint bandwidthConst = new BandwidthConstraint(Bandwidth.bps(60.0)); | ||
446 | + | ||
447 | + List<Constraint> constraints = new LinkedList<>(); | ||
448 | + constraints.add(bandwidthConst); | ||
449 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
450 | + | ||
451 | + assertThat(paths.iterator().next().cost(), is((double) 2)); | ||
452 | + } | ||
453 | + | ||
454 | + /** | ||
455 | + * Shared bandwidth as L1, L2 with its value 10 bps and bandwidth constraint as 20 bps. | ||
456 | + */ | ||
457 | + @Test | ||
458 | + public void testpathComputationCase5() { | ||
459 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
460 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20); | ||
461 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100); | ||
462 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80); | ||
463 | + | ||
464 | + List<Resource> resources = new LinkedList<>(); | ||
465 | + | ||
466 | + resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50)); | ||
467 | + resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50)); | ||
468 | + resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100)); | ||
469 | + resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100)); | ||
470 | + | ||
471 | + resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50)); | ||
472 | + resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50)); | ||
473 | + resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100)); | ||
474 | + resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100)); | ||
475 | + resourceService.allocate(IntentId.valueOf(70), resources); | ||
476 | + | ||
477 | + List<Constraint> constraints = new LinkedList<>(); | ||
478 | + | ||
479 | + List<Link> sharedLinks = new LinkedList<>(); | ||
480 | + | ||
481 | + List<Link> links = new LinkedList<>(); | ||
482 | + links.add(link1); | ||
483 | + links.add(link2); | ||
484 | + | ||
485 | + CostConstraint costConst = CostConstraint.of(COST); | ||
486 | + sharedLinks.addAll(links); | ||
487 | + SharedBandwidthConstraint sharedBw = new SharedBandwidthConstraint(sharedLinks, Bandwidth.bps(10), | ||
488 | + Bandwidth.bps(20.0)); | ||
489 | + constraints.add(sharedBw); | ||
490 | + constraints.add(costConst); | ||
491 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
492 | + assertThat(paths.iterator().next().links(), is(links)); | ||
493 | + assertThat(paths.iterator().next().cost(), is((double) 70)); | ||
494 | + } | ||
495 | + | ||
496 | + /** | ||
497 | + * Shared bandwidth as L1, L2 with its value 20 bps and bandwidth constraint as 10 bps. | ||
498 | + */ | ||
499 | + @Test | ||
500 | + public void testpathComputationCase6() { | ||
501 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
502 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20); | ||
503 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100); | ||
504 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80); | ||
505 | + | ||
506 | + List<Resource> resources = new LinkedList<>(); | ||
507 | + | ||
508 | + resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50)); | ||
509 | + resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50)); | ||
510 | + resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100)); | ||
511 | + resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100)); | ||
512 | + | ||
513 | + resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50)); | ||
514 | + resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50)); | ||
515 | + resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100)); | ||
516 | + resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100)); | ||
517 | + resourceService.allocate(IntentId.valueOf(70), resources); | ||
518 | + | ||
519 | + List<Constraint> constraints = new LinkedList<>(); | ||
520 | + | ||
521 | + List<Link> sharedLinks = new LinkedList<>(); | ||
522 | + | ||
523 | + List<Link> links = new LinkedList<>(); | ||
524 | + links.add(link1); | ||
525 | + links.add(link2); | ||
526 | + CostConstraint costConst = CostConstraint.of(COST); | ||
527 | + sharedLinks.addAll(links); | ||
528 | + SharedBandwidthConstraint sharedBwConst = new SharedBandwidthConstraint(sharedLinks, Bandwidth.bps(20), | ||
529 | + Bandwidth.bps(10.0)); | ||
530 | + constraints.add(sharedBwConst); | ||
531 | + constraints.add(costConst); | ||
532 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
533 | + | ||
534 | + assertThat(paths.iterator().next().links(), is(links)); | ||
535 | + assertThat(paths.iterator().next().cost(), is((double) 70)); | ||
536 | + } | ||
537 | + | ||
538 | + /** | ||
539 | + * Path without constraints. | ||
540 | + */ | ||
541 | + @Test | ||
542 | + public void testpathComputationCase7() { | ||
543 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
544 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20); | ||
545 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100); | ||
546 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80); | ||
547 | + List<Constraint> constraints = new LinkedList<>(); | ||
548 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
549 | + | ||
550 | + assertThat(paths.iterator().next().cost(), is((double) 2)); | ||
551 | + } | ||
552 | + | ||
553 | + /** | ||
554 | + * With TeCost as a constraints. | ||
555 | + */ | ||
556 | + @Test | ||
557 | + public void testpathComputationCase8() { | ||
558 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50); | ||
559 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20); | ||
560 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100); | ||
561 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80); | ||
562 | + | ||
563 | + CostConstraint tecostConst = CostConstraint.of(TE_COST); | ||
564 | + | ||
565 | + List<Constraint> constraints = new LinkedList<>(); | ||
566 | + constraints.add(tecostConst); | ||
567 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
568 | + | ||
569 | + List<Link> links = new LinkedList<>(); | ||
570 | + links.add(link1); | ||
571 | + links.add(link2); | ||
572 | + assertThat(paths.iterator().next().links(), is(links)); | ||
573 | + assertThat(paths.iterator().next().cost(), is((double) 70)); | ||
574 | + } | ||
575 | + | ||
576 | + /** | ||
577 | + * With device supporting RSVP capability as a constraints. | ||
578 | + */ | ||
579 | + @Test | ||
580 | + public void testpathComputationCase9() { | ||
581 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50); | ||
582 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20); | ||
583 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100); | ||
584 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80); | ||
585 | + | ||
586 | + CostConstraint tecostConst = CostConstraint.of(TE_COST); | ||
587 | + CapabilityConstraint capabilityConst = CapabilityConstraint | ||
588 | + .of(CapabilityConstraint.CapabilityType.WITH_SIGNALLING); | ||
589 | + | ||
590 | + List<Constraint> constraints = new LinkedList<>(); | ||
591 | + constraints.add(capabilityConst); | ||
592 | + constraints.add(tecostConst); | ||
593 | + //Device1 | ||
594 | + DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); | ||
595 | + builder.set(AnnotationKeys.TYPE, L3); | ||
596 | + builder.set(LSRID, "1.1.1.1"); | ||
597 | + addDevice(DEVICE1, builder); | ||
598 | + | ||
599 | + //Device2 | ||
600 | + builder = DefaultAnnotations.builder(); | ||
601 | + builder.set(AnnotationKeys.TYPE, L3); | ||
602 | + builder.set(LSRID, "2.2.2.2"); | ||
603 | + addDevice(DEVICE2, builder); | ||
604 | + | ||
605 | + //Device3 | ||
606 | + builder = DefaultAnnotations.builder(); | ||
607 | + builder.set(AnnotationKeys.TYPE, L3); | ||
608 | + builder.set(LSRID, "3.3.3.3"); | ||
609 | + addDevice(DEVICE3, builder); | ||
610 | + | ||
611 | + //Device4 | ||
612 | + builder = DefaultAnnotations.builder(); | ||
613 | + builder.set(AnnotationKeys.TYPE, L3); | ||
614 | + builder.set(LSRID, "4.4.4.4"); | ||
615 | + addDevice(DEVICE4, builder); | ||
616 | + | ||
617 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
618 | + | ||
619 | + List<Link> links = new LinkedList<>(); | ||
620 | + links.add(link1); | ||
621 | + links.add(link2); | ||
622 | + assertThat(paths.iterator().next().links(), is(links)); | ||
623 | + assertThat(paths.iterator().next().cost(), is((double) 70)); | ||
624 | + } | ||
625 | + | ||
626 | + /** | ||
627 | + * Devices supporting CR capability. | ||
628 | + */ | ||
629 | + @Test | ||
630 | + public void testpathComputationCase10() { | ||
631 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
632 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20); | ||
633 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100); | ||
634 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80); | ||
635 | + | ||
636 | + CapabilityConstraint capabilityConst = CapabilityConstraint | ||
637 | + .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR); | ||
638 | + | ||
639 | + List<Constraint> constraints = new LinkedList<>(); | ||
640 | + constraints.add(capabilityConst); | ||
641 | + CostConstraint costConst = CostConstraint.of(COST); | ||
642 | + constraints.add(costConst); | ||
643 | + //Device1 | ||
644 | + DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); | ||
645 | + builder.set(AnnotationKeys.TYPE, L3); | ||
646 | + builder.set(LSRID, "1.1.1.1"); | ||
647 | + addDevice(DEVICE1, builder); | ||
648 | + builder.set(PCECC_CAPABILITY, "true"); | ||
649 | + addDevice(PCEPDEVICE1, builder); | ||
650 | + | ||
651 | + //Device2 | ||
652 | + builder = DefaultAnnotations.builder(); | ||
653 | + builder.set(AnnotationKeys.TYPE, L3); | ||
654 | + builder.set(LSRID, "2.2.2.2"); | ||
655 | + addDevice(DEVICE2, builder); | ||
656 | + builder.set(PCECC_CAPABILITY, "true"); | ||
657 | + addDevice(PCEPDEVICE2, builder); | ||
658 | + | ||
659 | + //Device3 | ||
660 | + builder = DefaultAnnotations.builder(); | ||
661 | + builder.set(AnnotationKeys.TYPE, L3); | ||
662 | + builder.set(LSRID, "3.3.3.3"); | ||
663 | + addDevice(DEVICE3, builder); | ||
664 | + builder.set(PCECC_CAPABILITY, "true"); | ||
665 | + addDevice(PCEPDEVICE3, builder); | ||
666 | + | ||
667 | + //Device4 | ||
668 | + builder = DefaultAnnotations.builder(); | ||
669 | + builder.set(AnnotationKeys.TYPE, L3); | ||
670 | + builder.set(LSRID, "4.4.4.4"); | ||
671 | + addDevice(DEVICE4, builder); | ||
672 | + builder.set(PCECC_CAPABILITY, "true"); | ||
673 | + addDevice(PCEPDEVICE4, builder); | ||
674 | + | ||
675 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
676 | + | ||
677 | + List<Link> links = new LinkedList<>(); | ||
678 | + links.add(link1); | ||
679 | + links.add(link2); | ||
680 | + assertThat(paths.iterator().next().links(), is(links)); | ||
681 | + assertThat(paths.iterator().next().cost(), is((double) 70)); | ||
682 | + } | ||
683 | + | ||
684 | + /** | ||
685 | + * Device supporting SR capability. | ||
686 | + */ | ||
687 | + @Test | ||
688 | + public void testpathComputationCase11() { | ||
689 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
690 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20); | ||
691 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100); | ||
692 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80); | ||
693 | + | ||
694 | + CapabilityConstraint capabilityConst = CapabilityConstraint | ||
695 | + .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING); | ||
696 | + | ||
697 | + List<Constraint> constraints = new LinkedList<>(); | ||
698 | + constraints.add(capabilityConst); | ||
699 | + CostConstraint costConst = CostConstraint.of(COST); | ||
700 | + constraints.add(costConst); | ||
701 | + //Device1 | ||
702 | + DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); | ||
703 | + builder.set(AnnotationKeys.TYPE, L3); | ||
704 | + builder.set(LSRID, "1.1.1.1"); | ||
705 | + addDevice(DEVICE1, builder); | ||
706 | + builder.set(SR_CAPABILITY, "true"); | ||
707 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
708 | + addDevice(PCEPDEVICE1, builder); | ||
709 | + | ||
710 | + //Device2 | ||
711 | + builder = DefaultAnnotations.builder(); | ||
712 | + builder.set(AnnotationKeys.TYPE, L3); | ||
713 | + builder.set(LSRID, "2.2.2.2"); | ||
714 | + addDevice(DEVICE2, builder); | ||
715 | + builder.set(SR_CAPABILITY, "true"); | ||
716 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
717 | + addDevice(PCEPDEVICE2, builder); | ||
718 | + | ||
719 | + //Device3 | ||
720 | + builder = DefaultAnnotations.builder(); | ||
721 | + builder.set(AnnotationKeys.TYPE, L3); | ||
722 | + builder.set(LSRID, "3.3.3.3"); | ||
723 | + addDevice(DEVICE3, builder); | ||
724 | + builder.set(SR_CAPABILITY, "true"); | ||
725 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
726 | + addDevice(PCEPDEVICE3, builder); | ||
727 | + | ||
728 | + //Device4 | ||
729 | + builder = DefaultAnnotations.builder(); | ||
730 | + builder.set(AnnotationKeys.TYPE, L3); | ||
731 | + builder.set(LSRID, "4.4.4.4"); | ||
732 | + addDevice(DEVICE4, builder); | ||
733 | + builder.set(SR_CAPABILITY, "true"); | ||
734 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
735 | + addDevice(PCEPDEVICE4, builder); | ||
736 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
737 | + | ||
738 | + List<Link> links = new LinkedList<>(); | ||
739 | + links.add(link1); | ||
740 | + links.add(link2); | ||
741 | + assertThat(paths.iterator().next().links(), is(links)); | ||
742 | + assertThat(paths.iterator().next().cost(), is((double) 70)); | ||
743 | + } | ||
744 | + | ||
745 | + /** | ||
746 | + * Path with TE and SR capability constraint. | ||
747 | + */ | ||
748 | + @Test | ||
749 | + public void testpathComputationCase12() { | ||
750 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50); | ||
751 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20); | ||
752 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100); | ||
753 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80); | ||
754 | + | ||
755 | + CostConstraint tecostConst = CostConstraint.of(TE_COST); | ||
756 | + CapabilityConstraint capabilityConst = CapabilityConstraint | ||
757 | + .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING); | ||
758 | + | ||
759 | + List<Constraint> constraints = new LinkedList<>(); | ||
760 | + | ||
761 | + constraints.add(capabilityConst); | ||
762 | + constraints.add(tecostConst); | ||
763 | + //Device1 | ||
764 | + DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); | ||
765 | + builder.set(AnnotationKeys.TYPE, L3); | ||
766 | + builder.set(LSRID, "1.1.1.1"); | ||
767 | + addDevice(DEVICE1, builder); | ||
768 | + builder.set(SR_CAPABILITY, "true"); | ||
769 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
770 | + addDevice(PCEPDEVICE1, builder); | ||
771 | + | ||
772 | + //Device2 | ||
773 | + builder = DefaultAnnotations.builder(); | ||
774 | + builder.set(AnnotationKeys.TYPE, L3); | ||
775 | + builder.set(LSRID, "2.2.2.2"); | ||
776 | + addDevice(DEVICE2, builder); | ||
777 | + builder.set(SR_CAPABILITY, "true"); | ||
778 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
779 | + addDevice(PCEPDEVICE2, builder); | ||
780 | + | ||
781 | + //Device3 | ||
782 | + builder = DefaultAnnotations.builder(); | ||
783 | + builder.set(AnnotationKeys.TYPE, L3); | ||
784 | + builder.set(LSRID, "3.3.3.3"); | ||
785 | + addDevice(DEVICE3, builder); | ||
786 | + builder.set(SR_CAPABILITY, "true"); | ||
787 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
788 | + addDevice(PCEPDEVICE3, builder); | ||
789 | + | ||
790 | + //Device4 | ||
791 | + builder = DefaultAnnotations.builder(); | ||
792 | + builder.set(AnnotationKeys.TYPE, L3); | ||
793 | + builder.set(LSRID, "4.4.4.4"); | ||
794 | + addDevice(DEVICE4, builder); | ||
795 | + builder.set(SR_CAPABILITY, "true"); | ||
796 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
797 | + addDevice(PCEPDEVICE4, builder); | ||
798 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
799 | + | ||
800 | + List<Link> links = new LinkedList<>(); | ||
801 | + links.add(link1); | ||
802 | + links.add(link2); | ||
803 | + assertThat(paths.iterator().next().links(), is(links)); | ||
804 | + assertThat(paths.iterator().next().cost(), is((double) 70)); | ||
805 | + } | ||
806 | + | ||
807 | + /** | ||
808 | + * Path with capability constraint and with default cost. | ||
809 | + */ | ||
810 | + @Test | ||
811 | + public void testpathComputationCase13() { | ||
812 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50); | ||
813 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20); | ||
814 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100); | ||
815 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80); | ||
816 | + | ||
817 | + CapabilityConstraint capabilityConst = CapabilityConstraint | ||
818 | + .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING); | ||
819 | + | ||
820 | + List<Constraint> constraints = new LinkedList<>(); | ||
821 | + constraints.add(capabilityConst); | ||
822 | + //Device1 | ||
823 | + DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); | ||
824 | + builder.set(AnnotationKeys.TYPE, L3); | ||
825 | + builder.set(LSRID, "1.1.1.1"); | ||
826 | + addDevice(DEVICE1, builder); | ||
827 | + builder.set(SR_CAPABILITY, "true"); | ||
828 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
829 | + addDevice(PCEPDEVICE1, builder); | ||
830 | + | ||
831 | + //Device2 | ||
832 | + builder = DefaultAnnotations.builder(); | ||
833 | + builder.set(AnnotationKeys.TYPE, L3); | ||
834 | + builder.set(LSRID, "2.2.2.2"); | ||
835 | + addDevice(DEVICE2, builder); | ||
836 | + builder.set(SR_CAPABILITY, "true"); | ||
837 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
838 | + addDevice(PCEPDEVICE2, builder); | ||
839 | + | ||
840 | + //Device3 | ||
841 | + builder = DefaultAnnotations.builder(); | ||
842 | + builder.set(AnnotationKeys.TYPE, L3); | ||
843 | + builder.set(LSRID, "3.3.3.3"); | ||
844 | + addDevice(DEVICE3, builder); | ||
845 | + builder.set(SR_CAPABILITY, "true"); | ||
846 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
847 | + addDevice(PCEPDEVICE3, builder); | ||
848 | + | ||
849 | + //Device4 | ||
850 | + builder = DefaultAnnotations.builder(); | ||
851 | + builder.set(AnnotationKeys.TYPE, L3); | ||
852 | + builder.set(LSRID, "4.4.4.4"); | ||
853 | + addDevice(DEVICE4, builder); | ||
854 | + builder.set(SR_CAPABILITY, "true"); | ||
855 | + builder.set(LABEL_STACK_CAPABILITY, "true"); | ||
856 | + addDevice(PCEPDEVICE4, builder); | ||
857 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
858 | + | ||
859 | + List<Link> links = new LinkedList<>(); | ||
860 | + links.add(link1); | ||
861 | + links.add(link2); | ||
862 | + assertThat(paths.iterator().next().cost(), is((double) 2)); | ||
863 | + } | ||
864 | + | ||
865 | + /** | ||
866 | + * Test case with empty constraints. | ||
867 | + */ | ||
868 | + @Test | ||
869 | + public void testpathComputationCase14() { | ||
870 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50); | ||
871 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20); | ||
872 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100); | ||
873 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80); | ||
874 | + | ||
875 | + List<Constraint> constraints = new LinkedList<>(); | ||
876 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
877 | + | ||
878 | + assertThat(paths.iterator().next().cost(), is((double) 2)); | ||
879 | + } | ||
880 | + | ||
881 | + /** | ||
882 | + * Test case with constraints as null. | ||
883 | + */ | ||
884 | + @Test | ||
885 | + public void testpathComputationCase15() { | ||
886 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50); | ||
887 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20); | ||
888 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100); | ||
889 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80); | ||
890 | + | ||
891 | + List<Constraint> constraints = null; | ||
892 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
893 | + | ||
894 | + assertThat(paths.iterator().next().cost(), is((double) 2)); | ||
895 | + } | ||
896 | + | ||
897 | + /** | ||
898 | + * Path with cost constraint. | ||
899 | + */ | ||
900 | + @Test | ||
901 | + public void testpathComputationCase16() { | ||
902 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
903 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 100); | ||
904 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 10); | ||
905 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 10); | ||
906 | + Link link5 = addLink(DEVICE4, 90, DEVICE5, 100, true, 20); | ||
907 | + | ||
908 | + CostConstraint costConst = CostConstraint.of(COST); | ||
909 | + | ||
910 | + List<Constraint> constraints = new LinkedList<>(); | ||
911 | + constraints.add(costConst); | ||
912 | + Graph<TopologyVertex, TopologyEdge> graph = new AdjacencyListsGraph<>(of(D1, D2, D3, D4, D5), | ||
913 | + of(new DefaultTopologyEdge(D1, D2, link1), | ||
914 | + new DefaultTopologyEdge(D2, D4, link2), | ||
915 | + new DefaultTopologyEdge(D1, D3, link3), | ||
916 | + new DefaultTopologyEdge(D3, D4, link4), | ||
917 | + new DefaultTopologyEdge(D4, D5, link5))); | ||
918 | + | ||
919 | + GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = | ||
920 | + graphSearch().search(graph, D1, D5, weight(constraints), ALL_PATHS); | ||
921 | + ImmutableSet.Builder<Path> builder = ImmutableSet.builder(); | ||
922 | + for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { | ||
923 | + builder.add(networkPath(path)); | ||
924 | + } | ||
925 | + | ||
926 | + List<Link> links = new LinkedList<>(); | ||
927 | + links.add(link3); | ||
928 | + links.add(link4); | ||
929 | + links.add(link5); | ||
930 | + assertThat(builder.build().iterator().next().links(), is(links)); | ||
931 | + assertThat(builder.build().iterator().next().cost(), is((double) 40)); | ||
932 | + } | ||
933 | + | ||
934 | + /** | ||
935 | + * D3 doesn't support capability constraint, so path is L1-L2. | ||
936 | + */ | ||
937 | + @Test | ||
938 | + public void testpathComputationCase17() { | ||
939 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50); | ||
940 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20); | ||
941 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100); | ||
942 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80); | ||
943 | + | ||
944 | + CapabilityConstraint capabilityConst = CapabilityConstraint | ||
945 | + .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR); | ||
946 | + | ||
947 | + List<Constraint> constraints = new LinkedList<>(); | ||
948 | + constraints.add(capabilityConst); | ||
949 | + //Device1 | ||
950 | + DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); | ||
951 | + builder.set(AnnotationKeys.TYPE, L3); | ||
952 | + builder.set(LSRID, "1.1.1.1"); | ||
953 | + addDevice(DEVICE1, builder); | ||
954 | + builder.set(PCECC_CAPABILITY, "true"); | ||
955 | + addDevice(PCEPDEVICE1, builder); | ||
956 | + | ||
957 | + //Device2 | ||
958 | + builder = DefaultAnnotations.builder(); | ||
959 | + builder.set(AnnotationKeys.TYPE, L3); | ||
960 | + builder.set(LSRID, "2.2.2.2"); | ||
961 | + addDevice(DEVICE2, builder); | ||
962 | + builder.set(PCECC_CAPABILITY, "true"); | ||
963 | + addDevice(PCEPDEVICE2, builder); | ||
964 | + | ||
965 | + //Device4 | ||
966 | + builder = DefaultAnnotations.builder(); | ||
967 | + builder.set(AnnotationKeys.TYPE, L3); | ||
968 | + builder.set(LSRID, "4.4.4.4"); | ||
969 | + addDevice(DEVICE4, builder); | ||
970 | + builder.set(PCECC_CAPABILITY, "true"); | ||
971 | + addDevice(PCEPDEVICE4, builder); | ||
972 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
973 | + | ||
974 | + List<Link> links = new LinkedList<>(); | ||
975 | + links.add(link1); | ||
976 | + links.add(link2); | ||
977 | + | ||
978 | + assertThat(paths.iterator().next().links(), is(links)); | ||
979 | + assertThat(paths.iterator().next().cost(), is((double) 2)); | ||
980 | + } | ||
981 | + | ||
982 | + /** | ||
983 | + * L2 doesn't support cost constraint and D3 doesn't support capability constraint, both constraint fails hence no | ||
984 | + * path. | ||
985 | + */ | ||
986 | + @Test | ||
987 | + public void testpathComputationCase18() { | ||
988 | + Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50); | ||
989 | + Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20); | ||
990 | + Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 10); | ||
991 | + Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 10); | ||
992 | + | ||
993 | + CapabilityConstraint capabilityConst = CapabilityConstraint | ||
994 | + .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR); | ||
995 | + CostConstraint costConst = CostConstraint.of(COST); | ||
996 | + List<Constraint> constraints = new LinkedList<>(); | ||
997 | + constraints.add(capabilityConst); | ||
998 | + constraints.add(costConst); | ||
999 | + //Device1 | ||
1000 | + DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); | ||
1001 | + builder.set(AnnotationKeys.TYPE, L3); | ||
1002 | + builder.set(LSRID, "1.1.1.1"); | ||
1003 | + addDevice(DEVICE2, builder); | ||
1004 | + builder.set(PCECC_CAPABILITY, "true"); | ||
1005 | + addDevice(PCEPDEVICE1, builder); | ||
1006 | + | ||
1007 | + //Device2 | ||
1008 | + builder = DefaultAnnotations.builder(); | ||
1009 | + builder.set(AnnotationKeys.TYPE, L3); | ||
1010 | + builder.set(LSRID, "2.2.2.2"); | ||
1011 | + addDevice(DEVICE2, builder); | ||
1012 | + builder.set(PCECC_CAPABILITY, "true"); | ||
1013 | + addDevice(PCEPDEVICE2, builder); | ||
1014 | + | ||
1015 | + //Device4 | ||
1016 | + builder = DefaultAnnotations.builder(); | ||
1017 | + builder.set(AnnotationKeys.TYPE, L3); | ||
1018 | + builder.set(LSRID, "4.4.4.4"); | ||
1019 | + addDevice(DEVICE4, builder); | ||
1020 | + builder.set(PCECC_CAPABILITY, "true"); | ||
1021 | + addDevice(PCEPDEVICE4, builder); | ||
1022 | + Set<Path> paths = computePath(link1, link2, link3, link4, constraints); | ||
1023 | + | ||
1024 | + assertThat(paths, is(new HashSet<>())); | ||
1025 | + } | ||
1026 | + | ||
1027 | + private void addDevice(String device, DefaultAnnotations.Builder builder) { | ||
1028 | + deviceService.addDevice(new DefaultDevice(ProviderId.NONE, deviceId(device), Type.ROUTER, | ||
1029 | + UNKNOWN, UNKNOWN, UNKNOWN, | ||
1030 | + UNKNOWN, new ChassisId(), builder.build())); | ||
1031 | + } | ||
1032 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.pce.pceservice; | ||
17 | + | ||
18 | +import org.onosproject.net.resource.DiscreteResourceId; | ||
19 | +import org.onosproject.net.resource.ResourceAllocation; | ||
20 | +import org.onosproject.net.resource.ResourceConsumer; | ||
21 | +import org.onosproject.net.resource.ResourceId; | ||
22 | +import org.onosproject.net.resource.ResourceListener; | ||
23 | +import org.onosproject.net.resource.Resource; | ||
24 | +import org.onosproject.net.resource.ResourceService; | ||
25 | + | ||
26 | +import java.util.Collection; | ||
27 | +import java.util.List; | ||
28 | +import java.util.Set; | ||
29 | + | ||
30 | +/** | ||
31 | + * Adapter for resource service for path computation. | ||
32 | + */ | ||
33 | +public class ResourceServiceAdapter implements ResourceService { | ||
34 | + | ||
35 | + @Override | ||
36 | + public void addListener(ResourceListener listener) { | ||
37 | + // TODO Auto-generated method stub | ||
38 | + } | ||
39 | + | ||
40 | + @Override | ||
41 | + public void removeListener(ResourceListener listener) { | ||
42 | + // TODO Auto-generated method stub | ||
43 | + } | ||
44 | + | ||
45 | + @Override | ||
46 | + public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<Resource> resources) { | ||
47 | + // TODO Auto-generated method stub | ||
48 | + return null; | ||
49 | + } | ||
50 | + | ||
51 | + @Override | ||
52 | + public boolean release(List<ResourceAllocation> allocations) { | ||
53 | + // TODO Auto-generated method stub | ||
54 | + return false; | ||
55 | + } | ||
56 | + | ||
57 | + @Override | ||
58 | + public boolean release(ResourceConsumer consumer) { | ||
59 | + // TODO Auto-generated method stub | ||
60 | + return false; | ||
61 | + } | ||
62 | + | ||
63 | + @Override | ||
64 | + public List<ResourceAllocation> getResourceAllocations(ResourceId id) { | ||
65 | + // TODO Auto-generated method stub | ||
66 | + return null; | ||
67 | + } | ||
68 | + | ||
69 | + @Override | ||
70 | + public <T> Collection<ResourceAllocation> getResourceAllocations(DiscreteResourceId parent, Class<T> cls) { | ||
71 | + // TODO Auto-generated method stub | ||
72 | + return null; | ||
73 | + } | ||
74 | + | ||
75 | + @Override | ||
76 | + public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) { | ||
77 | + // TODO Auto-generated method stub | ||
78 | + return null; | ||
79 | + } | ||
80 | + | ||
81 | + @Override | ||
82 | + public Set<Resource> getAvailableResources(DiscreteResourceId parent) { | ||
83 | + // TODO Auto-generated method stub | ||
84 | + return null; | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) { | ||
89 | + // TODO Auto-generated method stub | ||
90 | + return null; | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) { | ||
95 | + // TODO Auto-generated method stub | ||
96 | + return null; | ||
97 | + } | ||
98 | + | ||
99 | + @Override | ||
100 | + public Set<Resource> getRegisteredResources(DiscreteResourceId parent) { | ||
101 | + // TODO Auto-generated method stub | ||
102 | + return null; | ||
103 | + } | ||
104 | + | ||
105 | + @Override | ||
106 | + public boolean isAvailable(Resource resource) { | ||
107 | + // TODO Auto-generated method stub | ||
108 | + return false; | ||
109 | + } | ||
110 | +} |
-
Please register or login to post a comment