blob: dd6d7e57b8859f04f148c8621dfa4d3b20dca6ba [file] [log] [blame]
Brian O'Connor66630c82014-10-02 21:08:19 -07001package org.onlab.onos.net.intent.impl;
2
Brian O'Connora4cab072014-10-03 18:46:39 -07003import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
alshabib8ca53902014-10-07 13:11:17 -07004import static org.slf4j.LoggerFactory.getLogger;
Brian O'Connora4cab072014-10-03 18:46:39 -07005
6import java.util.Iterator;
alshabib902d41b2014-10-07 16:52:05 -07007import java.util.List;
Brian O'Connorcb900f42014-10-07 21:55:33 -07008import java.util.concurrent.Future;
Brian O'Connora4cab072014-10-03 18:46:39 -07009
Brian O'Connor66630c82014-10-02 21:08:19 -070010import org.apache.felix.scr.annotations.Activate;
11import org.apache.felix.scr.annotations.Component;
12import org.apache.felix.scr.annotations.Deactivate;
13import org.apache.felix.scr.annotations.Reference;
14import org.apache.felix.scr.annotations.ReferenceCardinality;
15import org.onlab.onos.ApplicationId;
alshabib92c65ad2014-10-08 21:56:05 -070016import org.onlab.onos.CoreService;
Brian O'Connor66630c82014-10-02 21:08:19 -070017import org.onlab.onos.net.ConnectPoint;
18import org.onlab.onos.net.Link;
Brian O'Connorcb900f42014-10-07 21:55:33 -070019import org.onlab.onos.net.flow.CompletedBatchOperation;
Brian O'Connor66630c82014-10-02 21:08:19 -070020import org.onlab.onos.net.flow.DefaultFlowRule;
21import org.onlab.onos.net.flow.DefaultTrafficSelector;
Brian O'Connor66630c82014-10-02 21:08:19 -070022import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070023import org.onlab.onos.net.flow.FlowRuleBatchEntry;
24import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
25import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Brian O'Connor66630c82014-10-02 21:08:19 -070026import org.onlab.onos.net.flow.FlowRuleService;
27import org.onlab.onos.net.flow.TrafficSelector;
28import org.onlab.onos.net.flow.TrafficTreatment;
Brian O'Connor66630c82014-10-02 21:08:19 -070029import org.onlab.onos.net.intent.IntentExtensionService;
30import org.onlab.onos.net.intent.IntentInstaller;
31import org.onlab.onos.net.intent.PathIntent;
alshabib8ca53902014-10-07 13:11:17 -070032import org.slf4j.Logger;
Brian O'Connor66630c82014-10-02 21:08:19 -070033
alshabib902d41b2014-10-07 16:52:05 -070034import com.google.common.collect.Lists;
35
Brian O'Connor66630c82014-10-02 21:08:19 -070036/**
tom9a693fd2014-10-03 11:32:19 -070037 * Installer for {@link PathIntent path connectivity intents}.
Brian O'Connor66630c82014-10-02 21:08:19 -070038 */
39@Component(immediate = true)
tom9a693fd2014-10-03 11:32:19 -070040public class PathIntentInstaller implements IntentInstaller<PathIntent> {
41
alshabib8ca53902014-10-07 13:11:17 -070042 private final Logger log = getLogger(getClass());
43
Brian O'Connor66630c82014-10-02 21:08:19 -070044 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
45 protected IntentExtensionService intentManager;
46
47 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom9a693fd2014-10-03 11:32:19 -070048 protected FlowRuleService flowRuleService;
Brian O'Connor66630c82014-10-02 21:08:19 -070049
alshabib92c65ad2014-10-08 21:56:05 -070050 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 protected CoreService coreService;
52
53 private ApplicationId appId;
Brian O'Connor66630c82014-10-02 21:08:19 -070054
55 @Activate
56 public void activate() {
alshabib92c65ad2014-10-08 21:56:05 -070057 appId = coreService.registerApplication("org.onlab.onos.net.intent");
Brian O'Connor66630c82014-10-02 21:08:19 -070058 intentManager.registerInstaller(PathIntent.class, this);
59 }
60
61 @Deactivate
62 public void deactivate() {
63 intentManager.unregisterInstaller(PathIntent.class);
64 }
65
Brian O'Connorcb900f42014-10-07 21:55:33 -070066 /**
67 * Apply a list of FlowRules.
68 *
69 * @param rules rules to apply
70 */
71 private Future<CompletedBatchOperation> applyBatch(List<FlowRuleBatchEntry> rules) {
72 FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
73 Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
74 return future;
75// try {
76// //FIXME don't do this here
77// future.get();
78// } catch (InterruptedException | ExecutionException e) {
79// // TODO Auto-generated catch block
80// e.printStackTrace();
81// }
82 }
83
Brian O'Connor66630c82014-10-02 21:08:19 -070084 @Override
Brian O'Connorcb900f42014-10-07 21:55:33 -070085 public Future<CompletedBatchOperation> install(PathIntent intent) {
tom9a693fd2014-10-03 11:32:19 -070086 TrafficSelector.Builder builder =
tom85258ee2014-10-07 00:10:02 -070087 DefaultTrafficSelector.builder(intent.selector());
88 Iterator<Link> links = intent.path().links().iterator();
Brian O'Connor66630c82014-10-02 21:08:19 -070089 ConnectPoint prev = links.next().dst();
alshabib902d41b2014-10-07 16:52:05 -070090 List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
Brian O'Connor66630c82014-10-02 21:08:19 -070091 while (links.hasNext()) {
92 builder.matchInport(prev.port());
93 Link link = links.next();
tomf5c9d922014-10-03 15:22:03 -070094 TrafficTreatment treatment = builder()
95 .setOutput(link.src().port()).build();
alshabib902d41b2014-10-07 16:52:05 -070096
tom9a693fd2014-10-03 11:32:19 -070097 FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
Brian O'Connora4cab072014-10-03 18:46:39 -070098 builder.build(), treatment,
alshabib7911a052014-10-16 17:49:37 -070099 123, appId, 15);
alshabib902d41b2014-10-07 16:52:05 -0700100 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
Brian O'Connor66630c82014-10-02 21:08:19 -0700101 prev = link.dst();
102 }
Brian O'Connorcb900f42014-10-07 21:55:33 -0700103
104 return applyBatch(rules);
Brian O'Connor66630c82014-10-02 21:08:19 -0700105 }
106
107 @Override
Brian O'Connorcb900f42014-10-07 21:55:33 -0700108 public Future<CompletedBatchOperation> uninstall(PathIntent intent) {
Brian O'Connora4cab072014-10-03 18:46:39 -0700109 TrafficSelector.Builder builder =
tom85258ee2014-10-07 00:10:02 -0700110 DefaultTrafficSelector.builder(intent.selector());
111 Iterator<Link> links = intent.path().links().iterator();
Brian O'Connora4cab072014-10-03 18:46:39 -0700112 ConnectPoint prev = links.next().dst();
alshabib902d41b2014-10-07 16:52:05 -0700113 List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
Brian O'Connora4cab072014-10-03 18:46:39 -0700114
115 while (links.hasNext()) {
116 builder.matchInport(prev.port());
117 Link link = links.next();
118 TrafficTreatment treatment = builder()
119 .setOutput(link.src().port()).build();
120 FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
121 builder.build(), treatment,
122 123, appId, 600);
alshabib902d41b2014-10-07 16:52:05 -0700123 rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
Brian O'Connora4cab072014-10-03 18:46:39 -0700124 prev = link.dst();
125 }
Brian O'Connorcb900f42014-10-07 21:55:33 -0700126 return applyBatch(rules);
127 }
128
129 // TODO refactor below this line... ----------------------------
130
131 /**
132 * Generates the series of MatchActionOperations from the
133 * {@link FlowBatchOperation}.
134 * <p>
135 * FIXME: Currently supporting PacketPathFlow and SingleDstTreeFlow only.
136 * <p>
137 * FIXME: MatchActionOperations should have dependency field to the other
138 * match action operations, and this method should use this.
139 *
140 * @param op the {@link FlowBatchOperation} object
141 * @return the list of {@link MatchActionOperations} objects
142 */
143 /*
144 private List<MatchActionOperations>
145 generateMatchActionOperationsList(FlowBatchOperation op) {
146
147 // MatchAction operations at head (ingress) switches.
148 MatchActionOperations headOps = matchActionService.createOperationsList();
149
150 // MatchAction operations at rest of the switches.
151 MatchActionOperations tailOps = matchActionService.createOperationsList();
152
153 MatchActionOperations removeOps = matchActionService.createOperationsList();
154
155 for (BatchOperationEntry<Operator, ?> e : op.getOperations()) {
156
157 if (e.getOperator() == FlowBatchOperation.Operator.ADD) {
158 generateInstallMatchActionOperations(e, tailOps, headOps);
159 } else if (e.getOperator() == FlowBatchOperation.Operator.REMOVE) {
160 generateRemoveMatchActionOperations(e, removeOps);
161 } else {
162 throw new UnsupportedOperationException(
163 "FlowManager supports ADD and REMOVE operations only.");
164 }
165
166 }
167
168 return Arrays.asList(tailOps, headOps, removeOps);
169 }
170 */
171
172 /**
173 * Generates MatchActionOperations for an INSTALL FlowBatchOperation.
174 * <p/>
175 * FIXME: Currently only supports flows that generate exactly two match
176 * action operation sets.
177 *
178 * @param e Flow BatchOperationEntry
179 * @param tailOps MatchActionOperation set that the tail
180 * MatchActionOperations will be placed in
181 * @param headOps MatchActionOperation set that the head
182 * MatchActionOperations will be placed in
183 */
184 /*
185 private void generateInstallMatchActionOperations(
186 BatchOperationEntry<Operator, ?> e,
187 MatchActionOperations tailOps,
188 MatchActionOperations headOps) {
189
190 if (!(e.getTarget() instanceof Flow)) {
191 throw new IllegalStateException(
192 "The target is not Flow object: " + e.getTarget());
193 }
194
195 // Compile flows to match-actions
196 Flow flow = (Flow) e.getTarget();
197 List<MatchActionOperations> maOps = flow.compile(
198 e.getOperator(), matchActionService);
199 verifyNotNull(maOps, "Could not compile the flow: " + flow);
200 verify(maOps.size() == 2,
201 "The flow generates unspported match-action operations.");
202
203 // Map FlowId to MatchActionIds
204 for (MatchActionOperations maOp : maOps) {
205 for (MatchActionOperationEntry entry : maOp.getOperations()) {
206 flowMatchActionsMap.put(
207 KryoFactory.serialize(flow.getId()),
208 KryoFactory.serialize(entry.getTarget()));
209 }
210 }
211
212 // Merge match-action operations
213 for (MatchActionOperationEntry mae : maOps.get(0).getOperations()) {
214 verify(mae.getOperator() == MatchActionOperations.Operator.INSTALL);
215 tailOps.addOperation(mae);
216 }
217 for (MatchActionOperationEntry mae : maOps.get(1).getOperations()) {
218 verify(mae.getOperator() == MatchActionOperations.Operator.INSTALL);
219 headOps.addOperation(mae);
alshabib902d41b2014-10-07 16:52:05 -0700220 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700221 }
Brian O'Connorcb900f42014-10-07 21:55:33 -0700222 */
223 /**
224 * Generates MatchActionOperations for a REMOVE FlowBatchOperation.
225 *
226 * @param e Flow BatchOperationEntry
227 * @param removeOps MatchActionOperation set that the remove
228 * MatchActionOperations will be placed in
229 */
230 /*
231 private void generateRemoveMatchActionOperations(
232 BatchOperationEntry<Operator, ?> e,
233 MatchActionOperations removeOps) {
234
235 if (!(e.getTarget() instanceof FlowId)) {
236 throw new IllegalStateException(
237 "The target is not a FlowId object: " + e.getTarget());
238 }
239
240 // Compile flows to match-actions
241 FlowId flowId = (FlowId) e.getTarget();
242
243 for (byte[] matchActionIdBytes :
244 flowMatchActionsMap.remove(KryoFactory.serialize(flowId))) {
245 MatchActionId matchActionId = KryoFactory.deserialize(matchActionIdBytes);
246 removeOps.addOperation(new MatchActionOperationEntry(
247 MatchActionOperations.Operator.REMOVE, matchActionId));
248 }
249 }
250 */
Brian O'Connor66630c82014-10-02 21:08:19 -0700251}