blob: 51c4f7f6a04eabbc415383f9b5cb0bb3ce5d8abf [file] [log] [blame]
Jovana Vuleta1de61262017-06-14 11:10:29 +02001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Jovana Vuleta1de61262017-06-14 11:10:29 +02003 *
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
17package org.onosproject.drivers.hp;
18
19import com.google.common.cache.Cache;
20import com.google.common.cache.CacheBuilder;
21import com.google.common.cache.RemovalCause;
22import com.google.common.cache.RemovalNotification;
23import com.google.common.collect.ImmutableList;
24import org.onlab.osgi.ServiceDirectory;
Jovana Vuleta1de61262017-06-14 11:10:29 +020025import org.onlab.util.KryoNamespace;
26import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +010028import org.onosproject.net.Device;
Jovana Vuleta1de61262017-06-14 11:10:29 +020029import org.onosproject.net.DeviceId;
30import org.onosproject.net.behaviour.NextGroup;
31import org.onosproject.net.behaviour.Pipeliner;
32import org.onosproject.net.behaviour.PipelinerContext;
33import org.onosproject.net.device.DeviceService;
34import org.onosproject.net.driver.AbstractHandlerBehaviour;
Jovana Vuleta1de61262017-06-14 11:10:29 +020035import org.onosproject.net.flow.FlowRule;
36import org.onosproject.net.flow.FlowRuleOperations;
37import org.onosproject.net.flow.FlowRuleOperationsContext;
38import org.onosproject.net.flow.FlowRuleService;
39import org.onosproject.net.flow.TrafficSelector;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +010040import org.onosproject.net.flow.DefaultFlowRule;
Jovana Vuleta1de61262017-06-14 11:10:29 +020041import org.onosproject.net.flow.TrafficTreatment;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +010042import org.onosproject.net.flow.DefaultTrafficTreatment;
43import org.onosproject.net.flow.DefaultTrafficSelector;
Jovana Vuleta1de61262017-06-14 11:10:29 +020044import org.onosproject.net.flow.criteria.Criteria;
45import org.onosproject.net.flow.criteria.Criterion;
46import org.onosproject.net.flow.criteria.EthCriterion;
Jovana Vuleta1de61262017-06-14 11:10:29 +020047import org.onosproject.net.flow.criteria.IPCriterion;
48import org.onosproject.net.flow.criteria.PortCriterion;
49import org.onosproject.net.flow.criteria.VlanIdCriterion;
50import org.onosproject.net.flow.instructions.Instruction;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +010051import org.onosproject.net.flow.instructions.L2ModificationInstruction;
52import org.onosproject.net.flow.instructions.L3ModificationInstruction;
53import org.onosproject.net.flow.instructions.L4ModificationInstruction;
Jovana Vuleta1de61262017-06-14 11:10:29 +020054import org.onosproject.net.flowobjective.FilteringObjective;
55import org.onosproject.net.flowobjective.FlowObjectiveStore;
56import org.onosproject.net.flowobjective.ForwardingObjective;
57import org.onosproject.net.flowobjective.NextObjective;
58import org.onosproject.net.flowobjective.Objective;
59import org.onosproject.net.flowobjective.ObjectiveError;
60import org.onosproject.net.group.DefaultGroupKey;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +010061import org.onosproject.net.group.Group;
Jovana Vuleta1de61262017-06-14 11:10:29 +020062import org.onosproject.net.group.GroupKey;
63import org.onosproject.net.group.GroupService;
64import org.onosproject.net.meter.MeterService;
65import org.slf4j.Logger;
66
Alessio Giorgettic1518bb2017-11-17 17:01:26 +010067import java.util.HashSet;
Jovana Vuleta1de61262017-06-14 11:10:29 +020068import java.util.List;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +010069import java.util.Set;
Jovana Vuleta1de61262017-06-14 11:10:29 +020070import java.util.concurrent.TimeUnit;
71
72import static org.onosproject.net.flow.FlowRule.Builder;
73import static org.onosproject.net.flowobjective.Objective.Operation.ADD;
74import static org.slf4j.LoggerFactory.getLogger;
75
Jovana Vuleta1de61262017-06-14 11:10:29 +020076/**
77 * Abstraction of the HP pipeline handler.
Alessio Giorgettic1518bb2017-11-17 17:01:26 +010078 * Possibly compliant with all HP switches: tested with HP3800 (v2 module) and HP3500 (v1 module).
79 *
80 * These switches supports multiple OpenFlow instances.
81 * Each instance can be created with different pipeline models.
82 * This driver refers to OpenFlow instances created with "pipeline-model standard-match"
83 *
84 * With this model Table 100 is used for all entries that can be processed in hardware,
85 * whereas table 200 is used for entries processed in software.
86 *
87 * Trying to install a flow entries only supported in software in table 100 generates
88 * an OpenFlow error message from the switch.
89 *
90 * Installation of a flow entry supported in hardware in table 200 is allowed. But it strongly
91 * degrades forwarding performance.
92 *
93 * ---------------------------------------------
94 * --- SELECTION OF PROPER TABLE ID ---
95 * --- from device manual OpenFlow v1.3 for firmware 16.04 - (Appendix A)
96 * ---------------------------------------------
97 * --- Hardware differences between v1, v2 and v3 modules affect which features are supported
98 * in hardware/software. In this driver "TableIdForForwardingObjective()" function selects the
99 * proper table ID considering the hardware features of the device and the actual FlowObjective.
100 *
101 * ---------------------------------------------
102 * --- HPE switches support OpenFlow version 1.3.1 with following limitations.
103 * --- from device manual OpenFlow v1.3 for firmware 16.04 - (Appendix A)
104 *
105 *** UNSUPPORTED FLOW MATCHES --- (implemented using unsupported_criteria)
106 * ---------------------------------------------
107 * - METADATA - DONE
108 * - IP_ECN - DONE
109 * - SCTP_SRC, SCTP_DST - DONE
110 * - IPV6_ND_SLL, IPV6_ND_TLL - DONE
111 * - MPLS_LABEL, MPLS_TC, MPLS_BOS - DONE
112 * - PBB_ISID - DONE
113 * - TUNNEL_ID - DONE
114 * - IPV6_EXTHDR - DONE
115 *
116 *** UNSUPPORTED ACTIONS ---
117 * ---------------------------------------------
118 * - METADATA - DONE
119 * - QUEUE - DONE
120 * - OFPP_TABLE action - TODO
121 * - MPLS actions: Push-MPLS, Pop-MPLS, Set-MPLS TTL, Decrement MPLS TTL - DONE
122 * - Push-PBB, Pop-PBB actions - TODO
123 * - Copy TTL inwards/outwards actions - DONE
124 * - Decrement IP TTL - DONE
125 *
126 * ---------------------------------------------
127 * --- OTHER UNSUPPORTED FEATURES ---
128 * --- from device manual OpenFlow v1.3 for firmware 16.04
129 * ---------------------------------------------
130 * - Port commands: OFPPC_NO_STP, OFPPC_NO_RECV, OFPPC_NO_RECV_STP, OFPPC_NO_FWD - TODO
131 * - Handling of IP Fragments: OFPC_IP_REASM, OFPC_FRAG_REASM - TODO
132 *
133 * TODO MINOR: include above actions in the lists of unsupported features
134 *
135 * With current implementation, in case of unsupported features a WARNING message in generated
136 * in the ONOS log, but FlowRule is sent anyway to the device.
137 * The device will reply with an OFP_ERROR message.
138 * Use "debug openflow events" and "debug openflow errors" on the device to locally
139 * visualize detailed information on the specific error.
140 *
141 * TODO MAJOR: use OFP_TABLE_FEATURE messages to automate learning of unsupported features
142 *
Jovana Vuleta1de61262017-06-14 11:10:29 +0200143 */
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100144
Jovana Vuleta1de61262017-06-14 11:10:29 +0200145public abstract class AbstractHPPipeline extends AbstractHandlerBehaviour implements Pipeliner {
146
Jovana Vuleta1de61262017-06-14 11:10:29 +0200147 protected static final String APPLICATION_ID = "org.onosproject.drivers.hp.HPPipeline";
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100148
149 protected static final int HP_TABLE_ZERO = 0;
150 protected static final int HP_HARDWARE_TABLE = 100;
151 protected static final int HP_SOFTWARE_TABLE = 200;
152
Jovana Vuleta1de61262017-06-14 11:10:29 +0200153 public static final int CACHE_ENTRY_EXPIRATION_PERIOD = 20;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100154
Jovana Vuleta1de61262017-06-14 11:10:29 +0200155 private final Logger log = getLogger(getClass());
156 protected FlowRuleService flowRuleService;
157 protected GroupService groupService;
158 protected MeterService meterService;
159 protected FlowObjectiveStore flowObjectiveStore;
160 protected DeviceId deviceId;
161 protected ApplicationId appId;
162 protected DeviceService deviceService;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100163 protected Device device;
164 protected String deviceHwVersion;
Jovana Vuleta1de61262017-06-14 11:10:29 +0200165 protected KryoNamespace appKryo = new KryoNamespace.Builder()
166 .register(GroupKey.class)
167 .register(DefaultGroupKey.class)
168 .register(byte[].class)
169 .build("AbstractHPPipeline");
170 private ServiceDirectory serviceDirectory;
171 private CoreService coreService;
172 private Cache<Integer, NextObjective> pendingAddNext = CacheBuilder.newBuilder()
173 .expireAfterWrite(CACHE_ENTRY_EXPIRATION_PERIOD, TimeUnit.SECONDS)
174 .removalListener((RemovalNotification<Integer, NextObjective> notification) -> {
175 if (notification.getCause() == RemovalCause.EXPIRED) {
176 notification.getValue().context()
177 .ifPresent(c -> c.onError(notification.getValue(),
178 ObjectiveError.FLOWINSTALLATIONFAILED));
179 }
180 }).build();
181
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100182 /** Lists of unsupported features (firmware version K 16.04)
183 * If a FlowObjective uses one of these features a warning log message is generated.
184 */
185 protected Set<Criterion.Type> unsupportedCriteria = new HashSet<>();
186 protected Set<Instruction.Type> unsupportedInstructions = new HashSet<>();
187 protected Set<L2ModificationInstruction.L2SubType> unsupportedL2mod = new HashSet<>();
188 protected Set<L3ModificationInstruction.L3SubType> unsupportedL3mod = new HashSet<>();
189
190 /** Lists of Criteria and Instructions supported in hardware
191 * If a FlowObjective uses one of these features the FlowRule is intalled in HP_SOFTWARE_TABLE.
192 */
193 protected Set<Criterion.Type> hardwareCriteria = new HashSet<>();
194 protected Set<Instruction.Type> hardwareInstructions = new HashSet<>();
195 protected Set<L2ModificationInstruction.L2SubType> hardwareInstructionsL2mod = new HashSet<>();
196 protected Set<L3ModificationInstruction.L3SubType> hardwareInstructionsL3mod = new HashSet<>();
197 protected Set<L4ModificationInstruction.L4SubType> hardwareInstructionsL4mod = new HashSet<>();
198 protected Set<Group.Type> hardwareGroups = new HashSet<>();
199
Jovana Vuleta1de61262017-06-14 11:10:29 +0200200 /**
201 * Sets default table id.
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100202 * Using this solution all flow rules are installed on the "default" table
Jovana Vuleta1de61262017-06-14 11:10:29 +0200203 *
204 * @param ruleBuilder flow rule builder to be set table id
205 * @return flow rule builder with set table id for flow
206 */
207 protected abstract FlowRule.Builder setDefaultTableIdForFlowObjective(Builder ruleBuilder);
208
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100209 /**
210 * Return the proper table ID depending on the specific ForwardingObjective.
211 *
212 * HP switches supporting openflow have 3 tables (Pipeline Model: Standard Match)
213 * Table 0 is just a shortcut to table 100
214 * Table 100/200 are respectively used for rules processed in HARDWARE/SOFTWARE
215 *
216 * @param fwd ForwardingObjective
217 * @return table id
218 */
219 protected abstract int tableIdForForwardingObjective(ForwardingObjective fwd);
220
221 /**
222 * Return TRUE if ForwardingObjective fwd includes unsupported features.
223 *
224 * @param fwd ForwardingObjective
225 * @return boolean
226 */
227 protected abstract boolean checkUnSupportedFeatures(ForwardingObjective fwd);
228
Jovana Vuleta1de61262017-06-14 11:10:29 +0200229 @Override
230 public void init(DeviceId deviceId, PipelinerContext context) {
Jovana Vuleta1de61262017-06-14 11:10:29 +0200231 this.deviceId = deviceId;
232
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100233 serviceDirectory = context.directory();
Jovana Vuleta1de61262017-06-14 11:10:29 +0200234 coreService = serviceDirectory.get(CoreService.class);
235 flowRuleService = serviceDirectory.get(FlowRuleService.class);
236 groupService = serviceDirectory.get(GroupService.class);
237 meterService = serviceDirectory.get(MeterService.class);
238 deviceService = serviceDirectory.get(DeviceService.class);
239 flowObjectiveStore = context.store();
240
241 appId = coreService.registerApplication(APPLICATION_ID);
242
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100243 device = deviceService.getDevice(deviceId);
244 deviceHwVersion = device.hwVersion();
245
246 //Initialization of model specific features
247 log.info("HP Driver - Initializing unsupported features for switch {}", deviceHwVersion);
248 initUnSupportedFeatures();
249
250 log.debug("HP Driver - Initializing features supported in hardware");
251 initHardwareCriteria();
252 initHardwareInstructions();
253
254 log.debug("HP Driver - Initializing pipeline");
255 installHPTableZero();
256 installHPHardwareTable();
257 installHPSoftwareTable();
Jovana Vuleta1de61262017-06-14 11:10:29 +0200258 }
259
260 /**
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100261 * UnSupported features are specific of each model.
Jovana Vuleta1de61262017-06-14 11:10:29 +0200262 */
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100263 protected abstract void initUnSupportedFeatures();
264
265 /**
266 * Criteria supported in hardware are specific of each model.
267 */
268 protected abstract void initHardwareCriteria();
269
270 /**
271 * Instructions supported in hardware are specific of each model.
272 */
273 protected abstract void initHardwareInstructions();
274
275 /**
276 * HP Table 0 initialization.
277 * Installs rule goto HP_HARDWARE_TABLE in HP_TABLE_ZERO
278 */
279 private void installHPTableZero() {
280 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
281 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
282
283 treatment.transition(HP_HARDWARE_TABLE);
284
285 FlowRule rule = DefaultFlowRule.builder().forDevice(this.deviceId)
286 .withSelector(selector.build())
287 .withTreatment(treatment.build())
288 .withPriority(0)
289 .fromApp(appId)
290 .makePermanent()
291 .forTable(HP_TABLE_ZERO)
292 .build();
293
294 this.applyRules(true, rule);
295 }
296
297 /**
298 * HP hardware table initialization.
299 * Installs rule goto HP_SOFTWARE_TABLE in HP_HARDWARE_TABLE
300 */
301 private void installHPHardwareTable() {
302 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
303
304 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
305 //treatment.setOutput(PortNumber.NORMAL);
306 treatment.transition(HP_SOFTWARE_TABLE);
307
308 FlowRule rule = DefaultFlowRule.builder().forDevice(this.deviceId)
309 .withSelector(selector.build())
310 .withTreatment(treatment.build())
311 .withPriority(0)
312 .fromApp(appId)
313 .makePermanent()
314 .forTable(HP_HARDWARE_TABLE)
315 .build();
316
317 this.applyRules(true, rule);
318 }
319
320 /**
321 * Applies FlowRule.
322 * Installs or removes FlowRule.
323 *
324 * @param install - whether to install or remove rule
325 * @param rule - the rule to be installed or removed
326 */
327 private void applyRules(boolean install, FlowRule rule) {
328 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
329
330 ops = install ? ops.add(rule) : ops.remove(rule);
331 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
332 @Override
333 public void onSuccess(FlowRuleOperations ops) {
334 log.trace("HP Driver: provisioned " + rule.toString());
335
336 log.debug("HP Driver: - applyRules onSuccess rule {}", rule.toString());
337 }
338
339 @Override
340 public void onError(FlowRuleOperations ops) {
341 log.debug("HP Driver: applyRules onError rule: "
342 + rule.toString() + " in table: " + rule.tableId());
343 }
344 }));
345 }
346
347 /**
348 * HP software table initialization.
349 * No rules required.
350 */
351 private void installHPSoftwareTable() {}
Jovana Vuleta1de61262017-06-14 11:10:29 +0200352
353 protected void pass(Objective obj) {
354 obj.context().ifPresent(context -> context.onSuccess(obj));
355 }
356
357 protected void fail(Objective obj, ObjectiveError error) {
358 obj.context().ifPresent(context -> context.onError(obj, error));
359 }
360
361 @Override
362 public void forward(ForwardingObjective fwd) {
363
364 if (fwd.treatment() != null) {
365 // Deal with SPECIFIC and VERSATILE in the same manner.
366
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100367 /** If UNSUPPORTED features included in ForwardingObjective a warning message is generated.
368 * FlowRule is anyway sent to the device, device will reply with an OFP_ERROR.
369 * Moreover, checkUnSupportedFeatures function generates further warnings specifying
370 * each unsupported feature.
371 * */
372 if (checkUnSupportedFeatures(fwd)) {
373 log.warn("HP Driver - specified ForwardingObjective contains UNSUPPORTED FEATURES");
Jovana Vuleta1de61262017-06-14 11:10:29 +0200374 }
375
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100376 //Create the FlowRule starting from the ForwardingObjective
Jovana Vuleta1de61262017-06-14 11:10:29 +0200377 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
378 .forDevice(deviceId)
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100379 .withSelector(fwd.selector())
380 .withTreatment(fwd.treatment())
Jovana Vuleta1de61262017-06-14 11:10:29 +0200381 .withPriority(fwd.priority())
382 .fromApp(fwd.appId());
383
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100384 //Table to be used depends on the specific switch hardware and ForwardingObjective
385 ruleBuilder.forTable(tableIdForForwardingObjective(fwd));
Jovana Vuleta1de61262017-06-14 11:10:29 +0200386
387 if (fwd.permanent()) {
388 ruleBuilder.makePermanent();
389 } else {
390 ruleBuilder.makeTemporary(fwd.timeout());
391 }
392
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100393 log.debug("HP Driver - installing fwd.treatment {}", fwd.toString());
394
Jovana Vuleta1de61262017-06-14 11:10:29 +0200395 installObjective(ruleBuilder, fwd);
396
397 } else {
398 NextObjective nextObjective;
399 NextGroup next;
400 TrafficTreatment treatment;
401 if (fwd.op() == ADD) {
402 // Give a try to the cache. Doing an operation
403 // on the store seems to be very expensive.
404 nextObjective = pendingAddNext.getIfPresent(fwd.nextId());
405 // If the next objective is not present
406 // We will try with the store
407 if (nextObjective == null) {
408 next = flowObjectiveStore.getNextGroup(fwd.nextId());
409 // We verify that next was in the store and then de-serialize
410 // the treatment in order to re-build the flow rule.
411 if (next == null) {
412 fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
413 return;
414 }
415 treatment = appKryo.deserialize(next.data());
416 } else {
417 pendingAddNext.invalidate(fwd.nextId());
418 treatment = nextObjective.next().iterator().next();
419 }
420 } else {
421 // We get the NextGroup from the remove operation.
422 // Doing an operation on the store seems to be very expensive.
423 next = flowObjectiveStore.removeNextGroup(fwd.nextId());
424 if (next == null) {
425 fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
426 return;
427 }
428 treatment = appKryo.deserialize(next.data());
429 }
430 // If the treatment is null we cannot re-build the original flow
431 if (treatment == null) {
432 fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
433 return;
434 }
435 // Finally we build the flow rule and push to the flowrule subsystem.
436 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
437 .forDevice(deviceId)
438 .withSelector(fwd.selector())
439 .fromApp(fwd.appId())
440 .withPriority(fwd.priority())
441 .withTreatment(treatment);
442 if (fwd.permanent()) {
443 ruleBuilder.makePermanent();
444 } else {
445 ruleBuilder.makeTemporary(fwd.timeout());
446 }
447 installObjective(ruleBuilder, fwd);
448 }
449 }
450
451 /**
452 * Installs objective.
453 *
454 * @param ruleBuilder flow rule builder used to build rule from objective
455 * @param objective objective to be installed
456 */
457 protected void installObjective(FlowRule.Builder ruleBuilder, Objective objective) {
458 FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
459
460 switch (objective.op()) {
461 case ADD:
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100462 log.trace("HP Driver - Requested ADD of objective " + objective.toString());
Jovana Vuleta1de61262017-06-14 11:10:29 +0200463 FlowRule addRule = ruleBuilder.build();
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100464
465 log.trace("HP Driver - built rule is " + addRule.toString());
Jovana Vuleta1de61262017-06-14 11:10:29 +0200466 flowBuilder.add(addRule);
467 break;
468 case REMOVE:
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100469 log.trace("HP Driver - Requested REMOVE of objective " + objective.toString());
Jovana Vuleta1de61262017-06-14 11:10:29 +0200470 FlowRule removeRule = ruleBuilder.build();
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100471
472 log.trace("HP Driver - built rule is " + removeRule.toString());
Jovana Vuleta1de61262017-06-14 11:10:29 +0200473 flowBuilder.remove(removeRule);
474 break;
475 default:
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100476 log.warn("HP Driver - Unknown operation {}", objective.op());
Jovana Vuleta1de61262017-06-14 11:10:29 +0200477 }
478
479 flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
480 @Override
481 public void onSuccess(FlowRuleOperations ops) {
482 objective.context().ifPresent(context -> context.onSuccess(objective));
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100483 log.trace("HP Driver - Installed objective " + objective.toString());
Jovana Vuleta1de61262017-06-14 11:10:29 +0200484 }
485
486 @Override
487 public void onError(FlowRuleOperations ops) {
488 objective.context()
489 .ifPresent(context -> context.onError(objective, ObjectiveError.FLOWINSTALLATIONFAILED));
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100490 log.trace("HP Driver - Objective installation failed" + objective.toString());
Jovana Vuleta1de61262017-06-14 11:10:29 +0200491 }
492 }));
493 }
494
495 @Override
496 public void next(NextObjective nextObjective) {
497 switch (nextObjective.op()) {
498 case ADD:
499 // We insert the value in the cache
500 pendingAddNext.put(nextObjective.id(), nextObjective);
501 // Then in the store, this will unblock the queued fwd obj
502 flowObjectiveStore.putNextGroup(
503 nextObjective.id(),
504 new SingleGroup(nextObjective.next().iterator().next())
505 );
506 break;
507 case REMOVE:
508 break;
509 default:
510 log.warn("Unsupported operation {}", nextObjective.op());
511 }
512 nextObjective.context().ifPresent(context -> context.onSuccess(nextObjective));
513 }
514
515 @Override
516 public List<String> getNextMappings(NextGroup nextGroup) {
517 //TODO: to be implemented
518 return ImmutableList.of();
519 }
520
521 @Override
522 public void filter(FilteringObjective filteringObjective) {
523 if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
524 processFilter(filteringObjective,
525 filteringObjective.op() == Objective.Operation.ADD,
526 filteringObjective.appId());
527 } else {
528 fail(filteringObjective, ObjectiveError.UNSUPPORTED);
529 }
530 }
531
532 /**
533 * Filter processing and installation.
534 * Processes and installs filtering rules.
535 *
536 * @param filt
537 * @param install
538 * @param applicationId
539 */
540 private void processFilter(FilteringObjective filt, boolean install,
541 ApplicationId applicationId) {
542 // This driver only processes filtering criteria defined with switch
543 // ports as the key
544 PortCriterion port;
545 if (!filt.key().equals(Criteria.dummy()) &&
546 filt.key().type() == Criterion.Type.IN_PORT) {
547 port = (PortCriterion) filt.key();
548 } else {
549 log.warn("No key defined in filtering objective from app: {}. Not"
550 + "processing filtering objective", applicationId);
551 fail(filt, ObjectiveError.UNKNOWN);
552 return;
553 }
554 // convert filtering conditions for switch-intfs into flowrules
555 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
556 for (Criterion c : filt.conditions()) {
557 if (c.type() == Criterion.Type.ETH_DST) {
558 EthCriterion eth = (EthCriterion) c;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100559 FlowRule.Builder rule = processEthFilter(filt, eth, port);
Jovana Vuleta1de61262017-06-14 11:10:29 +0200560 rule.forDevice(deviceId)
561 .fromApp(applicationId);
562 ops = install ? ops.add(rule.build()) : ops.remove(rule.build());
563
564 } else if (c.type() == Criterion.Type.VLAN_VID) {
565 VlanIdCriterion vlan = (VlanIdCriterion) c;
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100566 FlowRule.Builder rule = processVlanFilter(filt, vlan, port);
Jovana Vuleta1de61262017-06-14 11:10:29 +0200567 rule.forDevice(deviceId)
568 .fromApp(applicationId);
569 ops = install ? ops.add(rule.build()) : ops.remove(rule.build());
570
571 } else if (c.type() == Criterion.Type.IPV4_DST) {
572 IPCriterion ip = (IPCriterion) c;
573 FlowRule.Builder rule = processIpFilter(filt, ip, port);
574 rule.forDevice(deviceId)
575 .fromApp(applicationId);
576 ops = install ? ops.add(rule.build()) : ops.remove(rule.build());
577
578 } else {
579 log.warn("Driver does not currently process filtering condition"
580 + " of type: {}", c.type());
581 fail(filt, ObjectiveError.UNSUPPORTED);
582 }
583 }
584 // apply filtering flow rules
585 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
586 @Override
587 public void onSuccess(FlowRuleOperations ops) {
588 pass(filt);
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100589 log.trace("HP Driver - Applied filtering rules");
Jovana Vuleta1de61262017-06-14 11:10:29 +0200590 }
591
592 @Override
593 public void onError(FlowRuleOperations ops) {
594 fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100595 log.trace("HP Driver - Failed to apply filtering rules");
Jovana Vuleta1de61262017-06-14 11:10:29 +0200596 }
597 }));
598 }
599
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100600 protected abstract Builder processEthFilter(FilteringObjective filt,
Jovana Vuleta1de61262017-06-14 11:10:29 +0200601 EthCriterion eth, PortCriterion port);
602
Alessio Giorgettic1518bb2017-11-17 17:01:26 +0100603 protected abstract Builder processVlanFilter(FilteringObjective filt,
Jovana Vuleta1de61262017-06-14 11:10:29 +0200604 VlanIdCriterion vlan, PortCriterion port);
605
606 protected abstract Builder processIpFilter(FilteringObjective filt,
607 IPCriterion ip, PortCriterion port);
608
609 private class SingleGroup implements NextGroup {
610
611 private TrafficTreatment nextActions;
612
613 SingleGroup(TrafficTreatment next) {
614 this.nextActions = next;
615 }
616
617 @Override
618 public byte[] data() {
619 return appKryo.serialize(nextActions);
620 }
621
622 public TrafficTreatment treatment() {
623 return nextActions;
624 }
625
626 }
627
628
629}