Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 1 | /* |
Brian O'Connor | a09fe5b | 2017-08-03 21:12:30 -0700 | [diff] [blame] | 2 | * Copyright 2016-present Open Networking Foundation |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 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 | */ |
Yuta HIGUCHI | d95d590 | 2016-06-27 00:18:45 -0700 | [diff] [blame] | 16 | package org.onosproject.net.optical.intent.impl.compiler; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 17 | |
| 18 | |
Ray Milkey | d84f89b | 2018-08-17 14:54:17 -0700 | [diff] [blame] | 19 | import org.osgi.service.component.annotations.Activate; |
| 20 | import org.osgi.service.component.annotations.Component; |
| 21 | import org.osgi.service.component.annotations.Deactivate; |
| 22 | import org.osgi.service.component.annotations.Reference; |
| 23 | import org.osgi.service.component.annotations.ReferenceCardinality; |
Ray Milkey | 7483e1b | 2018-02-07 15:43:01 -0800 | [diff] [blame] | 24 | import org.onlab.graph.ScalarWeight; |
| 25 | import org.onlab.graph.Weight; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 26 | import org.onosproject.core.ApplicationId; |
| 27 | import org.onosproject.core.CoreService; |
| 28 | import org.onosproject.net.ConnectPoint; |
| 29 | import org.onosproject.net.DeviceId; |
| 30 | import org.onosproject.net.Link; |
| 31 | import org.onosproject.net.LinkKey; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 32 | import org.onosproject.net.OduSignalId; |
| 33 | import org.onosproject.net.OduSignalType; |
| 34 | import org.onosproject.net.OduSignalUtils; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 35 | import org.onosproject.net.Path; |
| 36 | import org.onosproject.net.Port; |
| 37 | import org.onosproject.net.TributarySlot; |
| 38 | import org.onosproject.net.device.DeviceService; |
| 39 | import org.onosproject.net.flow.DefaultFlowRule; |
| 40 | import org.onosproject.net.flow.DefaultTrafficSelector; |
| 41 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 42 | import org.onosproject.net.flow.FlowRule; |
| 43 | import org.onosproject.net.flow.TrafficSelector; |
| 44 | import org.onosproject.net.flow.TrafficTreatment; |
| 45 | import org.onosproject.net.flow.criteria.Criteria; |
| 46 | import org.onosproject.net.flow.instructions.Instructions; |
| 47 | import org.onosproject.net.intent.FlowRuleIntent; |
| 48 | import org.onosproject.net.intent.Intent; |
| 49 | import org.onosproject.net.intent.IntentCompiler; |
| 50 | import org.onosproject.net.intent.IntentExtensionService; |
| 51 | import org.onosproject.net.intent.OpticalOduIntent; |
Luca Prete | 670ac5d | 2017-02-03 15:55:43 -0800 | [diff] [blame] | 52 | import org.onosproject.net.intent.PathIntent; |
HIGUCHI Yuta | 4c0ef6b | 2016-05-02 19:45:41 -0700 | [diff] [blame] | 53 | import org.onosproject.net.optical.OduCltPort; |
HIGUCHI Yuta | 5be3e82 | 2016-05-03 13:51:42 -0700 | [diff] [blame] | 54 | import org.onosproject.net.optical.OtuPort; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 55 | import org.onosproject.net.resource.Resource; |
| 56 | import org.onosproject.net.resource.ResourceService; |
| 57 | import org.onosproject.net.resource.ResourceAllocation; |
| 58 | import org.onosproject.net.resource.Resources; |
Ray Milkey | 7483e1b | 2018-02-07 15:43:01 -0800 | [diff] [blame] | 59 | import org.onosproject.net.topology.LinkWeigher; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 60 | import org.onosproject.net.topology.Topology; |
Ray Milkey | 7483e1b | 2018-02-07 15:43:01 -0800 | [diff] [blame] | 61 | import org.onosproject.net.topology.TopologyEdge; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 62 | import org.onosproject.net.topology.TopologyService; |
| 63 | import org.slf4j.Logger; |
| 64 | import org.slf4j.LoggerFactory; |
| 65 | |
| 66 | import com.google.common.collect.ImmutableList; |
| 67 | import com.google.common.collect.ImmutableSet; |
| 68 | import com.google.common.collect.Lists; |
| 69 | import com.google.common.collect.Sets; |
| 70 | |
| 71 | import java.util.ArrayList; |
| 72 | import java.util.Collections; |
| 73 | import java.util.HashMap; |
| 74 | import java.util.LinkedList; |
| 75 | import java.util.List; |
| 76 | import java.util.Map; |
| 77 | import java.util.Set; |
| 78 | import java.util.stream.Collectors; |
| 79 | import java.util.stream.Stream; |
| 80 | |
| 81 | import static com.google.common.base.Preconditions.checkArgument; |
| 82 | import static org.onosproject.net.LinkKey.linkKey; |
HIGUCHI Yuta | 4c0ef6b | 2016-05-02 19:45:41 -0700 | [diff] [blame] | 83 | import static org.onosproject.net.optical.device.OpticalDeviceServiceView.opticalView; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 84 | |
| 85 | /** |
| 86 | * An intent compiler for {@link org.onosproject.net.intent.OpticalOduIntent}. |
| 87 | */ |
| 88 | @Component(immediate = true) |
| 89 | public class OpticalOduIntentCompiler implements IntentCompiler<OpticalOduIntent> { |
| 90 | |
| 91 | private static final Logger log = LoggerFactory.getLogger(OpticalOduIntentCompiler.class); |
| 92 | |
Ray Milkey | d84f89b | 2018-08-17 14:54:17 -0700 | [diff] [blame] | 93 | @Reference(cardinality = ReferenceCardinality.MANDATORY) |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 94 | protected IntentExtensionService intentManager; |
| 95 | |
Ray Milkey | d84f89b | 2018-08-17 14:54:17 -0700 | [diff] [blame] | 96 | @Reference(cardinality = ReferenceCardinality.MANDATORY) |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 97 | protected CoreService coreService; |
| 98 | |
Ray Milkey | d84f89b | 2018-08-17 14:54:17 -0700 | [diff] [blame] | 99 | @Reference(cardinality = ReferenceCardinality.MANDATORY) |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 100 | protected TopologyService topologyService; |
| 101 | |
Ray Milkey | d84f89b | 2018-08-17 14:54:17 -0700 | [diff] [blame] | 102 | @Reference(cardinality = ReferenceCardinality.MANDATORY) |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 103 | protected DeviceService deviceService; |
| 104 | |
Ray Milkey | d84f89b | 2018-08-17 14:54:17 -0700 | [diff] [blame] | 105 | @Reference(cardinality = ReferenceCardinality.MANDATORY) |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 106 | protected ResourceService resourceService; |
| 107 | |
| 108 | private ApplicationId appId; |
| 109 | |
| 110 | @Activate |
| 111 | public void activate() { |
HIGUCHI Yuta | 4c0ef6b | 2016-05-02 19:45:41 -0700 | [diff] [blame] | 112 | deviceService = opticalView(deviceService); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 113 | appId = coreService.registerApplication("org.onosproject.net.intent"); |
| 114 | intentManager.registerCompiler(OpticalOduIntent.class, this); |
| 115 | } |
| 116 | |
| 117 | @Deactivate |
| 118 | public void deactivate() { |
| 119 | intentManager.unregisterCompiler(OpticalOduIntent.class); |
| 120 | } |
| 121 | |
| 122 | @Override |
| 123 | public List<Intent> compile(OpticalOduIntent intent, List<Intent> installable) { |
| 124 | // Check if ports are OduClt ports |
| 125 | ConnectPoint src = intent.getSrc(); |
| 126 | ConnectPoint dst = intent.getDst(); |
| 127 | Port srcPort = deviceService.getPort(src.deviceId(), src.port()); |
| 128 | Port dstPort = deviceService.getPort(dst.deviceId(), dst.port()); |
| 129 | checkArgument(srcPort instanceof OduCltPort); |
| 130 | checkArgument(dstPort instanceof OduCltPort); |
| 131 | |
| 132 | log.debug("Compiling optical ODU intent between {} and {}", src, dst); |
| 133 | |
| 134 | // Release of intent resources here is only a temporary solution for handling the |
| 135 | // case of recompiling due to intent restoration (when intent state is FAILED). |
| 136 | // TODO: try to release intent resources in IntentManager. |
Yuta HIGUCHI | 65d9d0e | 2017-05-04 12:44:32 -0700 | [diff] [blame] | 137 | resourceService.release(intent.key()); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 138 | |
| 139 | // Check OduClt ports availability |
| 140 | Resource srcPortResource = Resources.discrete(src.deviceId(), src.port()).resource(); |
| 141 | Resource dstPortResource = Resources.discrete(dst.deviceId(), dst.port()).resource(); |
| 142 | // If ports are not available, compilation fails |
| 143 | if (!Stream.of(srcPortResource, dstPortResource).allMatch(resourceService::isAvailable)) { |
Yuta HIGUCHI | d95d590 | 2016-06-27 00:18:45 -0700 | [diff] [blame] | 144 | throw new OpticalIntentCompilationException("Ports for the intent are not available. Intent: " + intent); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 145 | } |
| 146 | List<Resource> intentResources = new ArrayList<>(); |
| 147 | intentResources.add(srcPortResource); |
| 148 | intentResources.add(dstPortResource); |
| 149 | |
| 150 | // Calculate available light paths |
| 151 | Set<Path> paths = getOpticalPaths(intent); |
| 152 | |
| 153 | if (paths.isEmpty()) { |
Yuta HIGUCHI | d95d590 | 2016-06-27 00:18:45 -0700 | [diff] [blame] | 154 | throw new OpticalIntentCompilationException("Unable to find suitable lightpath for intent " + intent); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | // Use first path that can be successfully reserved |
| 158 | for (Path path : paths) { |
| 159 | |
| 160 | // Find available Tributary Slots on both directions of path |
| 161 | Map<LinkKey, Set<TributarySlot>> slotsMap = findAvailableTributarySlots(intent, path); |
| 162 | if (slotsMap.isEmpty()) { |
| 163 | continue; |
| 164 | } |
| 165 | List<Resource> tributarySlotResources = convertToResources(slotsMap); |
| 166 | if (!tributarySlotResources.stream().allMatch(resourceService::isAvailable)) { |
| 167 | continue; |
| 168 | } |
| 169 | |
| 170 | intentResources.addAll(tributarySlotResources); |
| 171 | |
| 172 | allocateResources(intent, intentResources); |
| 173 | |
| 174 | List<FlowRule> rules = new LinkedList<>(); |
| 175 | |
| 176 | // Create rules for forward and reverse path |
| 177 | rules = createRules(intent, intent.getSrc(), intent.getDst(), path, slotsMap, false); |
| 178 | if (intent.isBidirectional()) { |
| 179 | rules.addAll(createRules(intent, intent.getDst(), intent.getSrc(), path, slotsMap, true)); |
| 180 | } |
| 181 | |
Luca Prete | 670ac5d | 2017-02-03 15:55:43 -0800 | [diff] [blame] | 182 | return Collections.singletonList( |
| 183 | new FlowRuleIntent(appId, |
| 184 | intent.key(), |
| 185 | rules, |
| 186 | ImmutableSet.copyOf(path.links()), |
| 187 | PathIntent.ProtectionType.PRIMARY, |
| 188 | intent.resourceGroup())); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 189 | } |
| 190 | |
Yuta HIGUCHI | d95d590 | 2016-06-27 00:18:45 -0700 | [diff] [blame] | 191 | throw new OpticalIntentCompilationException("Unable to find suitable lightpath for intent " + intent); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | /** |
| 195 | * Find available TributarySlots across path. |
| 196 | * |
| 197 | * @param intent |
| 198 | * @param path path in OTU topology |
| 199 | * @return Map of Linkey and Set of available TributarySlots on its ports |
| 200 | */ |
| 201 | private Map<LinkKey, Set<TributarySlot>> findAvailableTributarySlots(OpticalOduIntent intent, Path path) { |
| 202 | Set<LinkKey> linkRequest = Sets.newHashSetWithExpectedSize(path.links().size()); |
| 203 | for (int i = 0; i < path.links().size(); i++) { |
| 204 | LinkKey link = linkKey(path.links().get(i)); |
| 205 | linkRequest.add(link); |
| 206 | } |
| 207 | |
| 208 | return findTributarySlots(intent, linkRequest); |
| 209 | } |
| 210 | |
| 211 | private List<Resource> convertToResources(Map<LinkKey, Set<TributarySlot>> slotsMap) { |
| 212 | // Same TributarySlots are used for both directions |
| 213 | Set<Resource> resources = slotsMap.entrySet().stream() |
| 214 | .flatMap(x -> x.getValue() |
| 215 | .stream() |
Ray Milkey | 88cc343 | 2017-03-30 17:19:08 -0700 | [diff] [blame] | 216 | .flatMap(ts -> Stream.of( |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 217 | Resources.discrete(x.getKey().src().deviceId(), x.getKey().src().port()) |
| 218 | .resource().child(ts), |
| 219 | Resources.discrete(x.getKey().dst().deviceId(), x.getKey().dst().port()) |
| 220 | .resource().child(ts)))) |
| 221 | .collect(Collectors.toSet()); |
| 222 | return (ImmutableList.copyOf(resources)); |
| 223 | } |
| 224 | |
| 225 | private void allocateResources(Intent intent, List<Resource> resources) { |
| 226 | // reserve all of required resources |
Yuta HIGUCHI | 65d9d0e | 2017-05-04 12:44:32 -0700 | [diff] [blame] | 227 | List<ResourceAllocation> allocations = resourceService.allocate(intent.key(), resources); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 228 | if (allocations.isEmpty()) { |
| 229 | log.info("Resource allocation for {} failed (resource request: {})", intent, resources); |
Yuta HIGUCHI | d95d590 | 2016-06-27 00:18:45 -0700 | [diff] [blame] | 230 | throw new OpticalIntentCompilationException("Unable to allocate resources: " + resources); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 231 | } |
| 232 | } |
| 233 | |
| 234 | private Map<LinkKey, Set<TributarySlot>> findTributarySlots(OpticalOduIntent intent, Set<LinkKey> links) { |
| 235 | OduSignalType oduSignalType = OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType()); |
| 236 | int requestedTsNum = oduSignalType.tributarySlots(); |
| 237 | |
| 238 | Map<LinkKey, Set<TributarySlot>> slotsMap = new HashMap<>(); |
| 239 | for (LinkKey link : links) { |
| 240 | Set<TributarySlot> common = findCommonTributarySlotsOnCps(link.src(), link.dst()); |
| 241 | if (common.isEmpty() || (common.size() < requestedTsNum)) { |
| 242 | log.debug("Failed to find TributarySlots on link {} requestedTsNum={}", link, requestedTsNum); |
| 243 | return Collections.emptyMap(); // failed to find enough available TributarySlots on a link |
| 244 | } |
| 245 | slotsMap.put(link, common.stream() |
| 246 | .limit(requestedTsNum) |
| 247 | .collect(Collectors.toSet())); |
| 248 | } |
| 249 | return slotsMap; |
| 250 | } |
| 251 | |
| 252 | /** |
| 253 | * Calculates optical paths in OTU topology. |
| 254 | * |
| 255 | * @param intent optical ODU intent |
| 256 | * @return set of paths in OTU topology |
| 257 | */ |
| 258 | private Set<Path> getOpticalPaths(OpticalOduIntent intent) { |
| 259 | // Route in OTU topology |
| 260 | Topology topology = topologyService.currentTopology(); |
| 261 | |
Ray Milkey | 7483e1b | 2018-02-07 15:43:01 -0800 | [diff] [blame] | 262 | |
| 263 | class Weigher implements LinkWeigher { |
| 264 | @Override |
| 265 | public Weight weight(TopologyEdge edge) { |
| 266 | if (edge.link().state() == Link.State.INACTIVE) { |
| 267 | return ScalarWeight.toWeight(-1); |
| 268 | } |
| 269 | if (edge.link().type() != Link.Type.OPTICAL) { |
| 270 | return ScalarWeight.toWeight(-1); |
| 271 | } |
| 272 | // Find path with available TributarySlots resources |
| 273 | if (!isAvailableTributarySlots(intent, edge.link())) { |
| 274 | return ScalarWeight.toWeight(-1); |
| 275 | } |
| 276 | return ScalarWeight.toWeight(1); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 277 | } |
Ray Milkey | 7483e1b | 2018-02-07 15:43:01 -0800 | [diff] [blame] | 278 | |
| 279 | @Override |
| 280 | public Weight getInitialWeight() { |
| 281 | return null; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 282 | } |
Ray Milkey | 7483e1b | 2018-02-07 15:43:01 -0800 | [diff] [blame] | 283 | |
| 284 | @Override |
| 285 | public Weight getNonViableWeight() { |
| 286 | return null; |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 287 | } |
Ray Milkey | 7483e1b | 2018-02-07 15:43:01 -0800 | [diff] [blame] | 288 | } |
| 289 | |
| 290 | |
| 291 | LinkWeigher weigher = new Weigher(); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 292 | |
| 293 | ConnectPoint start = intent.getSrc(); |
| 294 | ConnectPoint end = intent.getDst(); |
| 295 | |
Ray Milkey | 7483e1b | 2018-02-07 15:43:01 -0800 | [diff] [blame] | 296 | return topologyService.getPaths(topology, start.deviceId(), end.deviceId(), weigher); |
Rimon Ashkenazy | 27438ff | 2016-03-22 15:57:45 +0200 | [diff] [blame] | 297 | } |
| 298 | |
| 299 | private boolean isAvailableTributarySlots(OpticalOduIntent intent, Link link) { |
| 300 | OduSignalType oduSignalType = OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType()); |
| 301 | int requestedTsNum = oduSignalType.tributarySlots(); |
| 302 | |
| 303 | Set<TributarySlot> common = findCommonTributarySlotsOnCps(link.src(), link.dst()); |
| 304 | if (common.isEmpty() || (common.size() < requestedTsNum)) { |
| 305 | log.debug("Not enough available TributarySlots on link {} requestedTsNum={}", link, requestedTsNum); |
| 306 | return false; |
| 307 | } |
| 308 | return true; |
| 309 | } |
| 310 | |
| 311 | /** |
| 312 | * Create rules for the forward (or the reverse) path of the intent. |
| 313 | * |
| 314 | * @param intent OpticalOduIntent intent |
| 315 | * @param path path found for intent |
| 316 | * @param slotsMap Map of LinkKey and TributarySlots resources |
| 317 | * @return list of flow rules |
| 318 | */ |
| 319 | private List<FlowRule> createRules(OpticalOduIntent intent, ConnectPoint src, ConnectPoint dst, |
| 320 | Path path, Map<LinkKey, Set<TributarySlot>> slotsMap, boolean reverse) { |
| 321 | // Build the ingress OTN rule |
| 322 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
| 323 | selector.matchInPort(src.port()); |
| 324 | OduSignalType oduCltPortOduSignalType = |
| 325 | OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType()); |
| 326 | selector.add(Criteria.matchOduSignalType(oduCltPortOduSignalType)); |
| 327 | |
| 328 | List<FlowRule> rules = new LinkedList<>(); |
| 329 | ConnectPoint current = src; |
| 330 | |
| 331 | List<Link> links = ((!reverse) ? path.links() : Lists.reverse(path.links())); |
| 332 | |
| 333 | for (Link link : links) { |
| 334 | Set<TributarySlot> slots = slotsMap.get(linkKey(link)); |
| 335 | OtuPort otuPort = (OtuPort) (deviceService.getPort(link.src().deviceId(), link.src().port())); |
| 336 | OduSignalType otuPortOduSignalType = |
| 337 | OduSignalUtils.mappingOtuSignalTypeToOduSignalType(otuPort.signalType()); |
| 338 | |
| 339 | TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder(); |
| 340 | OduSignalId oduSignalId = null; |
| 341 | // use Instruction of OduSignalId only in case of ODU Multiplexing |
| 342 | if (oduCltPortOduSignalType != otuPortOduSignalType) { |
| 343 | oduSignalId = OduSignalUtils.buildOduSignalId(otuPortOduSignalType, slots); |
| 344 | treat.add(Instructions.modL1OduSignalId(oduSignalId)); |
| 345 | } |
| 346 | ConnectPoint next = ((!reverse) ? link.src() : link.dst()); |
| 347 | treat.setOutput(next.port()); |
| 348 | |
| 349 | FlowRule rule = createFlowRule(intent, current.deviceId(), selector.build(), treat.build()); |
| 350 | rules.add(rule); |
| 351 | |
| 352 | current = ((!reverse) ? link.dst() : link.src()); |
| 353 | selector = DefaultTrafficSelector.builder(); |
| 354 | selector.matchInPort(current.port()); |
| 355 | selector.add(Criteria.matchOduSignalType(oduCltPortOduSignalType)); |
| 356 | // use Criteria of OduSignalId only in case of ODU Multiplexing |
| 357 | if (oduCltPortOduSignalType != otuPortOduSignalType) { |
| 358 | selector.add(Criteria.matchOduSignalId(oduSignalId)); |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | // Build the egress OTN rule |
| 363 | TrafficTreatment.Builder treatLast = DefaultTrafficTreatment.builder(); |
| 364 | treatLast.setOutput(dst.port()); |
| 365 | |
| 366 | FlowRule rule = createFlowRule(intent, dst.deviceId(), selector.build(), treatLast.build()); |
| 367 | rules.add(rule); |
| 368 | |
| 369 | return rules; |
| 370 | } |
| 371 | |
| 372 | private FlowRule createFlowRule(OpticalOduIntent intent, DeviceId deviceId, |
| 373 | TrafficSelector selector, TrafficTreatment treat) { |
| 374 | return DefaultFlowRule.builder() |
| 375 | .forDevice(deviceId) |
| 376 | .withSelector(selector) |
| 377 | .withTreatment(treat) |
| 378 | .withPriority(intent.priority()) |
| 379 | .fromApp(appId) |
| 380 | .makePermanent() |
| 381 | .build(); |
| 382 | } |
| 383 | |
| 384 | /** |
| 385 | * Finds the common TributarySlots available on the two connect points. |
| 386 | * |
| 387 | * @param src source connect point |
| 388 | * @param dst dest connect point |
| 389 | * @return set of common TributarySlots on both connect points |
| 390 | */ |
| 391 | Set<TributarySlot> findCommonTributarySlotsOnCps(ConnectPoint src, ConnectPoint dst) { |
| 392 | Set<TributarySlot> forward = findTributarySlotsOnCp(src); |
| 393 | Set<TributarySlot> backward = findTributarySlotsOnCp(dst); |
| 394 | return Sets.intersection(forward, backward); |
| 395 | } |
| 396 | |
| 397 | /** |
| 398 | * Finds the TributarySlots available on the connect point. |
| 399 | * |
| 400 | * @param cp connect point |
| 401 | * @return set of TributarySlots available on the connect point |
| 402 | */ |
| 403 | Set<TributarySlot> findTributarySlotsOnCp(ConnectPoint cp) { |
| 404 | return resourceService.getAvailableResourceValues( |
| 405 | Resources.discrete(cp.deviceId(), cp.port()).id(), |
| 406 | TributarySlot.class); |
| 407 | } |
Ray Milkey | 88cc343 | 2017-03-30 17:19:08 -0700 | [diff] [blame] | 408 | } |