blob: d655cbe281354e2637e04b210fd24daa7ec992a1 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 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 */
Brian O'Connor66630c82014-10-02 21:08:19 -070016package org.onlab.onos.net.intent.impl;
17
Brian O'Connora4cab072014-10-03 18:46:39 -070018import java.util.Iterator;
alshabib902d41b2014-10-07 16:52:05 -070019import java.util.List;
Brian O'Connora4cab072014-10-03 18:46:39 -070020
Brian O'Connor66630c82014-10-02 21:08:19 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070026import org.onlab.onos.core.ApplicationId;
27import org.onlab.onos.core.CoreService;
Brian O'Connor66630c82014-10-02 21:08:19 -070028import org.onlab.onos.net.ConnectPoint;
29import org.onlab.onos.net.Link;
30import org.onlab.onos.net.flow.DefaultFlowRule;
31import org.onlab.onos.net.flow.DefaultTrafficSelector;
Brian O'Connor66630c82014-10-02 21:08:19 -070032import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070033import org.onlab.onos.net.flow.FlowRuleBatchEntry;
34import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
35import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Brian O'Connor66630c82014-10-02 21:08:19 -070036import org.onlab.onos.net.flow.TrafficSelector;
37import org.onlab.onos.net.flow.TrafficTreatment;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080038import org.onlab.onos.net.intent.Constraint;
Brian O'Connor66630c82014-10-02 21:08:19 -070039import org.onlab.onos.net.intent.IntentExtensionService;
40import org.onlab.onos.net.intent.IntentInstaller;
41import org.onlab.onos.net.intent.PathIntent;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080042import org.onlab.onos.net.resource.DefaultLinkResourceRequest;
Ray Milkeycaa450b2014-10-29 15:54:24 -070043import org.onlab.onos.net.resource.LinkResourceAllocations;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080044import org.onlab.onos.net.resource.LinkResourceRequest;
Ray Milkeycaa450b2014-10-29 15:54:24 -070045import org.onlab.onos.net.resource.LinkResourceService;
alshabib8ca53902014-10-07 13:11:17 -070046import org.slf4j.Logger;
Brian O'Connor66630c82014-10-02 21:08:19 -070047
alshabib902d41b2014-10-07 16:52:05 -070048import com.google.common.collect.Lists;
49
Ray Milkeycaa450b2014-10-29 15:54:24 -070050import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
51import static org.slf4j.LoggerFactory.getLogger;
52
Brian O'Connor66630c82014-10-02 21:08:19 -070053/**
Thomas Vachuska425a2d72014-10-29 11:28:28 -070054 * Installer for {@link PathIntent packet path connectivity intents}.
Brian O'Connor66630c82014-10-02 21:08:19 -070055 */
56@Component(immediate = true)
tom9a693fd2014-10-03 11:32:19 -070057public class PathIntentInstaller implements IntentInstaller<PathIntent> {
58
alshabib8ca53902014-10-07 13:11:17 -070059 private final Logger log = getLogger(getClass());
60
Brian O'Connor66630c82014-10-02 21:08:19 -070061 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 protected IntentExtensionService intentManager;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib92c65ad2014-10-08 21:56:05 -070065 protected CoreService coreService;
66
Ray Milkeycaa450b2014-10-29 15:54:24 -070067 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected LinkResourceService resourceService;
69
Ray Milkey8d3ce432014-11-07 16:21:10 -080070 protected ApplicationId appId;
Brian O'Connor66630c82014-10-02 21:08:19 -070071
72 @Activate
73 public void activate() {
alshabib92c65ad2014-10-08 21:56:05 -070074 appId = coreService.registerApplication("org.onlab.onos.net.intent");
Brian O'Connor66630c82014-10-02 21:08:19 -070075 intentManager.registerInstaller(PathIntent.class, this);
76 }
77
78 @Deactivate
79 public void deactivate() {
80 intentManager.unregisterInstaller(PathIntent.class);
81 }
82
83 @Override
Brian O'Connorf2dbde52014-10-10 16:20:24 -070084 public List<FlowRuleBatchOperation> install(PathIntent intent) {
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080085 LinkResourceAllocations allocations = allocateResources(intent);
Thomas Vachuskae3784c92014-10-29 21:09:10 -070086
tom9a693fd2014-10-03 11:32:19 -070087 TrafficSelector.Builder builder =
tom85258ee2014-10-07 00:10:02 -070088 DefaultTrafficSelector.builder(intent.selector());
89 Iterator<Link> links = intent.path().links().iterator();
Brian O'Connor66630c82014-10-02 21:08:19 -070090 ConnectPoint prev = links.next().dst();
alshabib902d41b2014-10-07 16:52:05 -070091 List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
Brian O'Connorf2dbde52014-10-10 16:20:24 -070092 // TODO Generate multiple batches
Brian O'Connor66630c82014-10-02 21:08:19 -070093 while (links.hasNext()) {
94 builder.matchInport(prev.port());
95 Link link = links.next();
alshabib5c05f862014-11-19 18:28:37 -080096 TrafficTreatment treatment =
97 // if this is the last flow rule, apply the intent's treatments
98 (links.hasNext() ? builder() : builder(intent.treatment()))
tomf5c9d922014-10-03 15:22:03 -070099 .setOutput(link.src().port()).build();
alshabib902d41b2014-10-07 16:52:05 -0700100
tom9a693fd2014-10-03 11:32:19 -0700101 FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
Brian O'Connor392619e2014-11-20 12:06:33 -0800102 builder.build(), treatment, 123, //FIXME 123
103 appId, (short) (intent.id().fingerprint() & 0xffff), 0, true);
Brian O'Connor427a1762014-11-19 18:40:32 -0800104 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule,
105 intent.id().fingerprint()));
Brian O'Connor66630c82014-10-02 21:08:19 -0700106 prev = link.dst();
107 }
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700108 return Lists.newArrayList(new FlowRuleBatchOperation(rules));
Brian O'Connor66630c82014-10-02 21:08:19 -0700109 }
110
111 @Override
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700112 public List<FlowRuleBatchOperation> uninstall(PathIntent intent) {
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800113 LinkResourceAllocations allocatedResources = resourceService.getAllocations(intent.id());
114 if (allocatedResources != null) {
115 resourceService.releaseResources(allocatedResources);
116 }
Brian O'Connora4cab072014-10-03 18:46:39 -0700117 TrafficSelector.Builder builder =
tom85258ee2014-10-07 00:10:02 -0700118 DefaultTrafficSelector.builder(intent.selector());
119 Iterator<Link> links = intent.path().links().iterator();
Brian O'Connora4cab072014-10-03 18:46:39 -0700120 ConnectPoint prev = links.next().dst();
alshabib902d41b2014-10-07 16:52:05 -0700121 List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700122 // TODO Generate multiple batches
Brian O'Connora4cab072014-10-03 18:46:39 -0700123 while (links.hasNext()) {
124 builder.matchInport(prev.port());
125 Link link = links.next();
alshabib2be9bea2014-11-24 18:26:07 -0500126 TrafficTreatment treatment = // if this is the last flow rule, apply the intent's treatments
127 (links.hasNext() ? builder() : builder(intent.treatment()))
128 .setOutput(link.src().port()).build();
Brian O'Connora4cab072014-10-03 18:46:39 -0700129 FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
130 builder.build(), treatment,
Brian O'Connor392619e2014-11-20 12:06:33 -0800131 123, appId, (short) (intent.id().fingerprint() & 0xffff), 0, true);
Brian O'Connor427a1762014-11-19 18:40:32 -0800132 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule,
133 intent.id().fingerprint()));
Brian O'Connora4cab072014-10-03 18:46:39 -0700134 prev = link.dst();
135 }
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700136 return Lists.newArrayList(new FlowRuleBatchOperation(rules));
Brian O'Connorcb900f42014-10-07 21:55:33 -0700137 }
138
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700139 @Override
140 public List<FlowRuleBatchOperation> replace(PathIntent oldIntent, PathIntent newIntent) {
141 // FIXME: implement this
142 List<FlowRuleBatchOperation> batches = Lists.newArrayList();
143 batches.addAll(uninstall(oldIntent));
144 batches.addAll(install(newIntent));
145 return batches;
146 }
147
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800148 /**
149 * Allocate resources required for an intent.
150 *
151 * @param intent intent to allocate resource for
152 * @return allocated resources if any are required, null otherwise
153 */
154 private LinkResourceAllocations allocateResources(PathIntent intent) {
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800155 LinkResourceRequest.Builder builder =
156 DefaultLinkResourceRequest.builder(intent.id(), intent.path().links());
157 for (Constraint constraint : intent.constraints()) {
158 builder.addConstraint(constraint);
159 }
160 LinkResourceRequest request = builder.build();
161 return request.resources().isEmpty() ? null : resourceService.requestResources(request);
Ray Milkeycaa450b2014-10-29 15:54:24 -0700162 }
163
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700164 // FIXME refactor below this line... ----------------------------
Brian O'Connorcb900f42014-10-07 21:55:33 -0700165
166 /**
167 * Generates the series of MatchActionOperations from the
168 * {@link FlowBatchOperation}.
169 * <p>
170 * FIXME: Currently supporting PacketPathFlow and SingleDstTreeFlow only.
171 * <p>
172 * FIXME: MatchActionOperations should have dependency field to the other
173 * match action operations, and this method should use this.
174 *
175 * @param op the {@link FlowBatchOperation} object
176 * @return the list of {@link MatchActionOperations} objects
177 */
178 /*
179 private List<MatchActionOperations>
180 generateMatchActionOperationsList(FlowBatchOperation op) {
181
182 // MatchAction operations at head (ingress) switches.
183 MatchActionOperations headOps = matchActionService.createOperationsList();
184
185 // MatchAction operations at rest of the switches.
186 MatchActionOperations tailOps = matchActionService.createOperationsList();
187
188 MatchActionOperations removeOps = matchActionService.createOperationsList();
189
190 for (BatchOperationEntry<Operator, ?> e : op.getOperations()) {
191
192 if (e.getOperator() == FlowBatchOperation.Operator.ADD) {
193 generateInstallMatchActionOperations(e, tailOps, headOps);
194 } else if (e.getOperator() == FlowBatchOperation.Operator.REMOVE) {
195 generateRemoveMatchActionOperations(e, removeOps);
196 } else {
197 throw new UnsupportedOperationException(
198 "FlowManager supports ADD and REMOVE operations only.");
199 }
200
201 }
202
203 return Arrays.asList(tailOps, headOps, removeOps);
204 }
205 */
206
207 /**
208 * Generates MatchActionOperations for an INSTALL FlowBatchOperation.
209 * <p/>
210 * FIXME: Currently only supports flows that generate exactly two match
211 * action operation sets.
212 *
213 * @param e Flow BatchOperationEntry
214 * @param tailOps MatchActionOperation set that the tail
215 * MatchActionOperations will be placed in
216 * @param headOps MatchActionOperation set that the head
217 * MatchActionOperations will be placed in
218 */
219 /*
220 private void generateInstallMatchActionOperations(
221 BatchOperationEntry<Operator, ?> e,
222 MatchActionOperations tailOps,
223 MatchActionOperations headOps) {
224
225 if (!(e.getTarget() instanceof Flow)) {
226 throw new IllegalStateException(
227 "The target is not Flow object: " + e.getTarget());
228 }
229
230 // Compile flows to match-actions
231 Flow flow = (Flow) e.getTarget();
232 List<MatchActionOperations> maOps = flow.compile(
233 e.getOperator(), matchActionService);
234 verifyNotNull(maOps, "Could not compile the flow: " + flow);
235 verify(maOps.size() == 2,
236 "The flow generates unspported match-action operations.");
237
238 // Map FlowId to MatchActionIds
239 for (MatchActionOperations maOp : maOps) {
240 for (MatchActionOperationEntry entry : maOp.getOperations()) {
241 flowMatchActionsMap.put(
242 KryoFactory.serialize(flow.getId()),
243 KryoFactory.serialize(entry.getTarget()));
244 }
245 }
246
247 // Merge match-action operations
248 for (MatchActionOperationEntry mae : maOps.get(0).getOperations()) {
249 verify(mae.getOperator() == MatchActionOperations.Operator.INSTALL);
250 tailOps.addOperation(mae);
251 }
252 for (MatchActionOperationEntry mae : maOps.get(1).getOperations()) {
253 verify(mae.getOperator() == MatchActionOperations.Operator.INSTALL);
254 headOps.addOperation(mae);
alshabib902d41b2014-10-07 16:52:05 -0700255 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700256 }
Brian O'Connorcb900f42014-10-07 21:55:33 -0700257 */
258 /**
259 * Generates MatchActionOperations for a REMOVE FlowBatchOperation.
260 *
261 * @param e Flow BatchOperationEntry
262 * @param removeOps MatchActionOperation set that the remove
263 * MatchActionOperations will be placed in
264 */
265 /*
266 private void generateRemoveMatchActionOperations(
267 BatchOperationEntry<Operator, ?> e,
268 MatchActionOperations removeOps) {
269
270 if (!(e.getTarget() instanceof FlowId)) {
271 throw new IllegalStateException(
272 "The target is not a FlowId object: " + e.getTarget());
273 }
274
275 // Compile flows to match-actions
276 FlowId flowId = (FlowId) e.getTarget();
277
278 for (byte[] matchActionIdBytes :
279 flowMatchActionsMap.remove(KryoFactory.serialize(flowId))) {
280 MatchActionId matchActionId = KryoFactory.deserialize(matchActionIdBytes);
281 removeOps.addOperation(new MatchActionOperationEntry(
282 MatchActionOperations.Operator.REMOVE, matchActionId));
283 }
284 }
285 */
Brian O'Connor66630c82014-10-02 21:08:19 -0700286}