blob: f2a20fa2a93bd03dd2ec40a7433197291fe3b577 [file] [log] [blame]
Sho SHIMIZUee2aa652015-02-25 18:56:43 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Sho SHIMIZUee2aa652015-02-25 18:56:43 -08003 *
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 HIGUCHId95d5902016-06-27 00:18:45 -070016package org.onosproject.net.optical.intent.impl.compiler;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080017
Marc De Leenheerb6f95e22017-03-15 12:18:59 -070018import com.google.common.collect.ImmutableSet;
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -070019import com.google.common.collect.Lists;
alessiod4a2b842019-04-30 18:43:17 +020020import org.onosproject.net.ConnectPoint;
21import org.onosproject.net.Device;
22import org.onosproject.net.DeviceId;
23import org.onosproject.net.Link;
24import org.onosproject.net.PortNumber;
25import org.onosproject.net.Port;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070026import org.osgi.service.component.annotations.Activate;
27import org.osgi.service.component.annotations.Component;
28import org.osgi.service.component.annotations.Deactivate;
29import org.osgi.service.component.annotations.Reference;
30import org.osgi.service.component.annotations.ReferenceCardinality;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080031import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
Yuta HIGUCHI09697d02017-03-03 16:53:39 -080033import org.onosproject.net.Device.Type;
Yuta HIGUCHI09697d02017-03-03 16:53:39 -080034import org.onosproject.net.device.DeviceService;
35import org.onosproject.net.device.DeviceServiceAdapter;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080036import org.onosproject.net.flow.DefaultFlowRule;
37import org.onosproject.net.flow.DefaultTrafficSelector;
38import org.onosproject.net.flow.DefaultTrafficTreatment;
39import org.onosproject.net.flow.FlowRule;
40import org.onosproject.net.flow.TrafficSelector;
41import org.onosproject.net.flow.TrafficTreatment;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070042import org.onosproject.net.flow.criteria.Criteria;
43import org.onosproject.net.flow.instructions.Instructions;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080044import org.onosproject.net.intent.FlowRuleIntent;
45import org.onosproject.net.intent.Intent;
46import org.onosproject.net.intent.IntentCompiler;
47import org.onosproject.net.intent.IntentExtensionService;
48import org.onosproject.net.intent.OpticalPathIntent;
Luca Prete670ac5d2017-02-03 15:55:43 -080049import org.onosproject.net.intent.PathIntent;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070050import org.slf4j.Logger;
51import org.slf4j.LoggerFactory;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080052
Sho SHIMIZU98ffca82015-05-11 08:39:24 -070053import java.util.Collections;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080054import java.util.LinkedList;
55import java.util.List;
Yuta HIGUCHI09697d02017-03-03 16:53:39 -080056import java.util.Optional;
Marc De Leenheerb6f95e22017-03-15 12:18:59 -070057import java.util.Set;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080058
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080059@Component(immediate = true)
60public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathIntent> {
61
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070062 private static final Logger log = LoggerFactory.getLogger(OpticalPathIntentCompiler.class);
63
Ray Milkeyd84f89b2018-08-17 14:54:17 -070064 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080065 protected IntentExtensionService intentManager;
66
Ray Milkeyd84f89b2018-08-17 14:54:17 -070067 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080068 protected CoreService coreService;
69
Ray Milkeyd84f89b2018-08-17 14:54:17 -070070 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yuta HIGUCHI09697d02017-03-03 16:53:39 -080071 protected DeviceService deviceService = new DeviceServiceAdapter();
72
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080073 private ApplicationId appId;
Marc De Leenheerb6f95e22017-03-15 12:18:59 -070074 // Devices which are wavelength transparent and thus do not require wavelength-based match/actions
75 private static final Set<Type> TRANSPARENT_DEVICES =
76 ImmutableSet.of(Type.OPTICAL_AMPLIFIER, Type.FIBER_SWITCH);
77 // Devices which don't accept flow rules
78 private static final Set<Type> NO_FLOWRULE_DEVICES =
79 ImmutableSet.of(Type.OPTICAL_AMPLIFIER);
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080080
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080081 @Activate
82 public void activate() {
83 appId = coreService.registerApplication("org.onosproject.net.intent");
84 intentManager.registerCompiler(OpticalPathIntent.class, this);
85 }
86
87 @Deactivate
88 public void deactivate() {
89 intentManager.unregisterCompiler(OpticalPathIntent.class);
90 }
91
92 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -080093 public List<Intent> compile(OpticalPathIntent intent, List<Intent> installable) {
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070094 log.debug("Compiling optical path intent between {} and {}", intent.src(), intent.dst());
95
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -070096 // Create rules for forward and reverse path
97 List<FlowRule> rules = createRules(intent);
98 if (intent.isBidirectional()) {
99 rules.addAll(createReverseRules(intent));
100 }
101
Luca Prete670ac5d2017-02-03 15:55:43 -0800102 return Collections.singletonList(
103 new FlowRuleIntent(appId,
fahadnaeemkhan0e1b4d92018-02-08 16:40:08 -0800104 intent.key(),
105 rules,
106 intent.resources(),
107 PathIntent.ProtectionType.PRIMARY,
108 intent.resourceGroup()
Luca Prete670ac5d2017-02-03 15:55:43 -0800109 )
110 );
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800111 }
112
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700113 /**
114 * Create rules for the forward path of the intent.
115 *
116 * @param intent the intent
117 * @return list of flow rules
118 */
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700119 private List<FlowRule> createRules(OpticalPathIntent intent) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800120 TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
121 selectorBuilder.matchInPort(intent.src().port());
122
123 List<FlowRule> rules = new LinkedList<>();
fahadnaeemkhan0e1b4d92018-02-08 16:40:08 -0800124
125 /*
126 * especial case for 0 hop when srcDeviceId = dstDeviceId
127 * and path contain only one fake default path.
128 */
129 if (intent.src().deviceId().equals(intent.dst().deviceId()) &&
130 intent.path().links().size() == 1) {
131 log.debug("handling 0 hop case for intent {}", intent);
132 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
133 if (!isTransparent(intent.src().deviceId())) {
134 treatmentBuilder.add(Instructions.modL0Lambda(intent.lambda()));
135 }
136 treatmentBuilder.setOutput(intent.dst().port());
137
138 FlowRule rule = DefaultFlowRule.builder()
139 .forDevice(intent.src().deviceId())
140 .withSelector(selectorBuilder.build())
141 .withTreatment(treatmentBuilder.build())
142 .withPriority(intent.priority())
143 .fromApp(appId)
144 .makePermanent()
145 .build();
146 rules.add(rule);
147 return rules;
148 }
149
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700150 ConnectPoint current = intent.src();
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800151
152 for (Link link : intent.path().links()) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800153 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
Marc De Leenheer43b91ad2017-03-17 14:45:28 -0700154 if (!isTransparent(current.deviceId())) {
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700155 treatmentBuilder.add(Instructions.modL0Lambda(intent.lambda()));
156 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800157 treatmentBuilder.setOutput(link.src().port());
158
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700159 FlowRule rule = DefaultFlowRule.builder()
160 .forDevice(current.deviceId())
161 .withSelector(selectorBuilder.build())
162 .withTreatment(treatmentBuilder.build())
Brian O'Connor81134662015-06-25 17:23:33 -0400163 .withPriority(intent.priority())
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700164 .fromApp(appId)
165 .makePermanent()
166 .build();
Marc De Leenheer43b91ad2017-03-17 14:45:28 -0700167 selectorBuilder = DefaultTrafficSelector.builder();
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800168
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700169 if (!isNoFlowRule(current.deviceId())) {
Yuta HIGUCHI09697d02017-03-03 16:53:39 -0800170 rules.add(rule);
171 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800172
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700173 current = link.dst();
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800174 selectorBuilder.matchInPort(link.dst().port());
Marc De Leenheer43b91ad2017-03-17 14:45:28 -0700175 if (!isTransparent(current.deviceId())) {
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700176 selectorBuilder.add(Criteria.matchLambda(intent.lambda()));
177 selectorBuilder.add(Criteria.matchOchSignalType(intent.signalType()));
178 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800179 }
180
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700181 // Build the egress ROADM rule
182 TrafficTreatment.Builder treatmentLast = DefaultTrafficTreatment.builder();
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800183 treatmentLast.setOutput(intent.dst().port());
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700184
185 FlowRule rule = new DefaultFlowRule.Builder()
186 .forDevice(intent.dst().deviceId())
187 .withSelector(selectorBuilder.build())
188 .withTreatment(treatmentLast.build())
Brian O'Connor81134662015-06-25 17:23:33 -0400189 .withPriority(intent.priority())
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700190 .fromApp(appId)
191 .makePermanent()
192 .build();
Yuta HIGUCHI09697d02017-03-03 16:53:39 -0800193
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700194 if (!isNoFlowRule(intent.dst().deviceId())) {
Yuta HIGUCHI09697d02017-03-03 16:53:39 -0800195 rules.add(rule);
196 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800197
198 return rules;
199 }
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700200
201 /**
202 * Create rules for the reverse path of the intent.
203 *
204 * @param intent the intent
205 * @return list of flow rules
206 */
207 private List<FlowRule> createReverseRules(OpticalPathIntent intent) {
208 TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
alessiod4a2b842019-04-30 18:43:17 +0200209 selectorBuilder.matchInPort(reversePort(intent.dst().deviceId(), intent.dst().port()));
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700210
211 List<FlowRule> rules = new LinkedList<>();
fahadnaeemkhan0e1b4d92018-02-08 16:40:08 -0800212
213 /*
214 * especial case for 0 hop when srcDeviceId = dstDeviceId
215 * and path contain only one fake default path.
216 */
217 if (intent.src().deviceId().equals(intent.dst().deviceId()) &&
218 intent.path().links().size() == 1) {
219 log.debug("handling 0 hop reverse path case for intent {}", intent);
220 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
221 if (!isTransparent(intent.src().deviceId())) {
222 treatmentBuilder.add(Instructions.modL0Lambda(intent.lambda()));
223 }
alessiod4a2b842019-04-30 18:43:17 +0200224 treatmentBuilder.setOutput(reversePort(intent.src().deviceId(), intent.src().port()));
fahadnaeemkhan0e1b4d92018-02-08 16:40:08 -0800225
226 FlowRule rule = DefaultFlowRule.builder()
227 .forDevice(intent.src().deviceId())
228 .withSelector(selectorBuilder.build())
229 .withTreatment(treatmentBuilder.build())
230 .withPriority(intent.priority())
231 .fromApp(appId)
232 .makePermanent()
233 .build();
234 rules.add(rule);
235 return rules;
236 }
237
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700238 ConnectPoint current = intent.dst();
239
240 for (Link link : Lists.reverse(intent.path().links())) {
241 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
Marc De Leenheer43b91ad2017-03-17 14:45:28 -0700242 if (!isTransparent(current.deviceId())) {
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700243 treatmentBuilder.add(Instructions.modL0Lambda(intent.lambda()));
244 }
alessiod4a2b842019-04-30 18:43:17 +0200245 treatmentBuilder.setOutput(reversePort(link.dst().deviceId(), link.dst().port()));
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700246
247 FlowRule rule = DefaultFlowRule.builder()
248 .forDevice(current.deviceId())
249 .withSelector(selectorBuilder.build())
250 .withTreatment(treatmentBuilder.build())
Brian O'Connor81134662015-06-25 17:23:33 -0400251 .withPriority(intent.priority())
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700252 .fromApp(appId)
253 .makePermanent()
254 .build();
Marc De Leenheer43b91ad2017-03-17 14:45:28 -0700255 selectorBuilder = DefaultTrafficSelector.builder();
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700256
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700257 if (!isNoFlowRule(current.deviceId())) {
Yuta HIGUCHI09697d02017-03-03 16:53:39 -0800258 rules.add(rule);
259 }
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700260
261 current = link.src();
alessiod4a2b842019-04-30 18:43:17 +0200262 selectorBuilder.matchInPort(reversePort(link.src().deviceId(), link.src().port()));
Marc De Leenheer43b91ad2017-03-17 14:45:28 -0700263 if (!isTransparent(current.deviceId())) {
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700264 selectorBuilder.add(Criteria.matchLambda(intent.lambda()));
265 selectorBuilder.add(Criteria.matchOchSignalType(intent.signalType()));
266 }
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700267 }
268
269 // Build the egress ROADM rule
270 TrafficTreatment.Builder treatmentLast = DefaultTrafficTreatment.builder();
alessiod4a2b842019-04-30 18:43:17 +0200271 treatmentLast.setOutput(reversePort(intent.src().deviceId(), intent.src().port()));
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700272
273 FlowRule rule = new DefaultFlowRule.Builder()
274 .forDevice(intent.src().deviceId())
275 .withSelector(selectorBuilder.build())
276 .withTreatment(treatmentLast.build())
Brian O'Connor81134662015-06-25 17:23:33 -0400277 .withPriority(intent.priority())
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700278 .fromApp(appId)
279 .makePermanent()
280 .build();
Yuta HIGUCHI09697d02017-03-03 16:53:39 -0800281
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700282 if (!isNoFlowRule(intent.src().deviceId())) {
Yuta HIGUCHI09697d02017-03-03 16:53:39 -0800283 rules.add(rule);
284 }
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700285
286 return rules;
287 }
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700288
289 /**
alessiod4a2b842019-04-30 18:43:17 +0200290 * Returns the PortNum of reverse port if annotation is present, otherwise return PortNum of the port itself.
291 * In the OpenROADM YANG models it is used the term "partner-port.
292 *
293 * @param portNumber the port
294 * @return the PortNum of reverse port if annotation is present, otherwise PortNum of the port itself.
295 */
296 private PortNumber reversePort(DeviceId deviceId, PortNumber portNumber) {
297 Port port = deviceService.getPort(deviceId, portNumber);
298
299 String reversePort = port.annotations().value(OpticalPathIntent.REVERSE_PORT_ANNOTATION_KEY);
300 if (reversePort != null) {
301 PortNumber reversePortNumber = PortNumber.portNumber(reversePort);
302 return reversePortNumber;
303 } else {
304 return portNumber;
305 }
306 }
307
308 /**
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700309 * Returns true if device does not accept flow rules, false otherwise.
310 *
311 * @param deviceId the device
312 * @return true if device does not accept flow rule, false otherwise
313 */
314 private boolean isNoFlowRule(DeviceId deviceId) {
315 return NO_FLOWRULE_DEVICES.contains(
316 Optional.ofNullable(deviceService.getDevice(deviceId))
317 .map(Device::type)
318 .orElse(Type.OTHER));
319 }
320
321 /**
322 * Returns true if device is wavelength transparent, false otherwise.
323 *
324 * @param deviceId the device
325 * @return true if wavelength transparent, false otherwise
326 */
327 private boolean isTransparent(DeviceId deviceId) {
328 return TRANSPARENT_DEVICES.contains(
329 Optional.ofNullable(deviceService.getDevice(deviceId))
fahadnaeemkhan0e1b4d92018-02-08 16:40:08 -0800330 .map(Device::type)
331 .orElse(Type.OTHER));
Marc De Leenheerb6f95e22017-03-15 12:18:59 -0700332 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800333}