Committed by
Gerrit Code Review
implementing q-in-q support
implementing filtering objectives for punting rules Change-Id: I73945df31c4d5aa40ab4b07fc6818edd083178fb
Showing
1 changed file
with
345 additions
and
56 deletions
... | @@ -15,8 +15,13 @@ | ... | @@ -15,8 +15,13 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.driver.pipeline; | 16 | package org.onosproject.driver.pipeline; |
17 | 17 | ||
18 | +import com.google.common.collect.Lists; | ||
19 | +import org.apache.commons.lang3.tuple.ImmutablePair; | ||
20 | +import org.apache.commons.lang3.tuple.Pair; | ||
18 | import org.onlab.osgi.ServiceDirectory; | 21 | import org.onlab.osgi.ServiceDirectory; |
19 | import org.onlab.packet.EthType; | 22 | import org.onlab.packet.EthType; |
23 | +import org.onlab.packet.IPv4; | ||
24 | +import org.onlab.packet.VlanId; | ||
20 | import org.onosproject.core.ApplicationId; | 25 | import org.onosproject.core.ApplicationId; |
21 | import org.onosproject.core.CoreService; | 26 | import org.onosproject.core.CoreService; |
22 | import org.onosproject.net.DefaultAnnotations; | 27 | import org.onosproject.net.DefaultAnnotations; |
... | @@ -41,24 +46,38 @@ import org.onosproject.net.flow.FlowRuleOperationsContext; | ... | @@ -41,24 +46,38 @@ import org.onosproject.net.flow.FlowRuleOperationsContext; |
41 | import org.onosproject.net.flow.FlowRuleService; | 46 | import org.onosproject.net.flow.FlowRuleService; |
42 | import org.onosproject.net.flow.TrafficSelector; | 47 | import org.onosproject.net.flow.TrafficSelector; |
43 | import org.onosproject.net.flow.TrafficTreatment; | 48 | import org.onosproject.net.flow.TrafficTreatment; |
49 | +import org.onosproject.net.flow.criteria.Criteria; | ||
50 | +import org.onosproject.net.flow.criteria.Criterion; | ||
51 | +import org.onosproject.net.flow.criteria.EthTypeCriterion; | ||
52 | +import org.onosproject.net.flow.criteria.IPProtocolCriterion; | ||
53 | +import org.onosproject.net.flow.criteria.PortCriterion; | ||
54 | +import org.onosproject.net.flow.instructions.Instruction; | ||
44 | import org.onosproject.net.flow.instructions.Instructions; | 55 | import org.onosproject.net.flow.instructions.Instructions; |
56 | +import org.onosproject.net.flow.instructions.L2ModificationInstruction; | ||
45 | import org.onosproject.net.flowobjective.FilteringObjective; | 57 | import org.onosproject.net.flowobjective.FilteringObjective; |
46 | import org.onosproject.net.flowobjective.ForwardingObjective; | 58 | import org.onosproject.net.flowobjective.ForwardingObjective; |
47 | import org.onosproject.net.flowobjective.NextObjective; | 59 | import org.onosproject.net.flowobjective.NextObjective; |
60 | +import org.onosproject.net.flowobjective.Objective; | ||
48 | import org.onosproject.net.flowobjective.ObjectiveError; | 61 | import org.onosproject.net.flowobjective.ObjectiveError; |
49 | -import org.onosproject.net.packet.PacketPriority; | ||
50 | import org.onosproject.net.provider.AbstractProvider; | 62 | import org.onosproject.net.provider.AbstractProvider; |
51 | import org.onosproject.net.provider.ProviderId; | 63 | import org.onosproject.net.provider.ProviderId; |
52 | import org.slf4j.Logger; | 64 | import org.slf4j.Logger; |
53 | 65 | ||
66 | +import java.util.Collection; | ||
67 | +import java.util.List; | ||
68 | +import java.util.Optional; | ||
69 | +import java.util.stream.Collectors; | ||
70 | + | ||
54 | import static com.google.common.base.Preconditions.checkNotNull; | 71 | import static com.google.common.base.Preconditions.checkNotNull; |
55 | import static org.slf4j.LoggerFactory.getLogger; | 72 | import static org.slf4j.LoggerFactory.getLogger; |
56 | 73 | ||
57 | /** | 74 | /** |
58 | * Pipeliner for OLT device. | 75 | * Pipeliner for OLT device. |
59 | */ | 76 | */ |
77 | + | ||
60 | public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { | 78 | public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { |
61 | 79 | ||
80 | + private static final Integer QQ_TABLE = 1; | ||
62 | private final Logger log = getLogger(getClass()); | 81 | private final Logger log = getLogger(getClass()); |
63 | 82 | ||
64 | static final ProviderId PID = new ProviderId("olt", "org.onosproject.olt", true); | 83 | static final ProviderId PID = new ProviderId("olt", "org.onosproject.olt", true); |
... | @@ -75,9 +94,9 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { | ... | @@ -75,9 +94,9 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { |
75 | 94 | ||
76 | private DeviceProvider provider = new AnnotationProvider(); | 95 | private DeviceProvider provider = new AnnotationProvider(); |
77 | 96 | ||
78 | - | ||
79 | @Override | 97 | @Override |
80 | public void init(DeviceId deviceId, PipelinerContext context) { | 98 | public void init(DeviceId deviceId, PipelinerContext context) { |
99 | + log.debug("Initiate OLT pipeline"); | ||
81 | this.serviceDirectory = context.directory(); | 100 | this.serviceDirectory = context.directory(); |
82 | this.deviceId = deviceId; | 101 | this.deviceId = deviceId; |
83 | DeviceProviderRegistry registry = | 102 | DeviceProviderRegistry registry = |
... | @@ -85,105 +104,375 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { | ... | @@ -85,105 +104,375 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { |
85 | flowRuleService = serviceDirectory.get(FlowRuleService.class); | 104 | flowRuleService = serviceDirectory.get(FlowRuleService.class); |
86 | coreService = serviceDirectory.get(CoreService.class); | 105 | coreService = serviceDirectory.get(CoreService.class); |
87 | 106 | ||
88 | - /*try { | ||
89 | - DeviceProviderService providerService = registry.register(provider); | ||
90 | - providerService.deviceConnected(deviceId, | ||
91 | - description(deviceId, DEVICE, OLT)); | ||
92 | - } finally { | ||
93 | - registry.unregister(provider); | ||
94 | - }*/ | ||
95 | - | ||
96 | appId = coreService.registerApplication( | 107 | appId = coreService.registerApplication( |
97 | "org.onosproject.driver.OLTPipeline"); | 108 | "org.onosproject.driver.OLTPipeline"); |
98 | 109 | ||
99 | - TrafficSelector selector = DefaultTrafficSelector.builder() | 110 | + } |
100 | - .matchEthType(EthType.EtherType.EAPOL.ethType().toShort()) | ||
101 | - .build(); | ||
102 | 111 | ||
103 | - TrafficTreatment treatment = DefaultTrafficTreatment.builder() | 112 | + @Override |
104 | - .punt() | 113 | + public void filter(FilteringObjective filter) { |
105 | - .build(); | 114 | + Instructions.OutputInstruction output; |
106 | 115 | ||
107 | - FlowRule flowRule = new DefaultFlowRule(deviceId, selector, treatment, | 116 | + if (filter.meta() != null && !filter.meta().immediate().isEmpty()) { |
108 | - PacketPriority.CONTROL.priorityValue(), | 117 | + output = (Instructions.OutputInstruction) filter.meta().immediate().stream() |
109 | - appId, 0, true, null); | 118 | + .filter(t -> t.type().equals(Instruction.Type.OUTPUT)) |
119 | + .limit(1) | ||
120 | + .findFirst().get(); | ||
110 | 121 | ||
111 | - //flowRuleService.applyFlowRules(flowRule); | 122 | + if (output != null && !output.port().equals(PortNumber.CONTROLLER)) { |
123 | + fail(filter, ObjectiveError.UNSUPPORTED); | ||
124 | + return; | ||
125 | + } | ||
126 | + } else { | ||
127 | + fail(filter, ObjectiveError.BADPARAMS); | ||
128 | + return; | ||
112 | } | 129 | } |
113 | 130 | ||
114 | - @Override | 131 | + if (filter.key().type() != Criterion.Type.IN_PORT) { |
115 | - public void filter(FilteringObjective filter) { | 132 | + fail(filter, ObjectiveError.BADPARAMS); |
116 | - throw new UnsupportedOperationException("OLT does not filter."); | 133 | + return; |
117 | } | 134 | } |
118 | 135 | ||
136 | + EthTypeCriterion ethType = (EthTypeCriterion) | ||
137 | + filterForCriterion(filter.conditions(), Criterion.Type.ETH_TYPE); | ||
138 | + | ||
139 | + if (ethType == null) { | ||
140 | + fail(filter, ObjectiveError.BADPARAMS); | ||
141 | + return; | ||
142 | + } | ||
143 | + | ||
144 | + if (ethType.ethType().equals(EthType.EtherType.EAPOL)) { | ||
145 | + provisionEapol(filter, ethType, output); | ||
146 | + } else if (ethType.ethType().equals(EthType.EtherType.IPV4)) { | ||
147 | + IPProtocolCriterion ipProto = (IPProtocolCriterion) | ||
148 | + filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO); | ||
149 | + if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) { | ||
150 | + provisionIGMP(filter, ethType, ipProto, output); | ||
151 | + } | ||
152 | + } else { | ||
153 | + fail(filter, ObjectiveError.UNSUPPORTED); | ||
154 | + } | ||
155 | + | ||
156 | + } | ||
157 | + | ||
158 | + | ||
119 | @Override | 159 | @Override |
120 | public void forward(ForwardingObjective fwd) { | 160 | public void forward(ForwardingObjective fwd) { |
121 | - FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); | 161 | + TrafficTreatment treatment = fwd.treatment(); |
162 | + | ||
163 | + List<Instruction> instructions = treatment.allInstructions(); | ||
122 | 164 | ||
123 | - if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) { | 165 | + Optional<Instruction> vlanIntruction = instructions.stream() |
124 | - throw new UnsupportedOperationException( | 166 | + .filter(i -> i.type() == Instruction.Type.L2MODIFICATION) |
125 | - "Only VERSATILE is supported."); | 167 | + .filter(i -> ((L2ModificationInstruction) i).subtype() == |
168 | + L2ModificationInstruction.L2SubType.VLAN_PUSH || | ||
169 | + ((L2ModificationInstruction) i).subtype() == | ||
170 | + L2ModificationInstruction.L2SubType.VLAN_POP) | ||
171 | + .findAny(); | ||
172 | + | ||
173 | + if (!vlanIntruction.isPresent()) { | ||
174 | + fail(fwd, ObjectiveError.BADPARAMS); | ||
175 | + return; | ||
126 | } | 176 | } |
127 | 177 | ||
128 | - boolean isPunt = fwd.treatment().immediate().stream().anyMatch(i -> { | 178 | + L2ModificationInstruction vlanIns = |
129 | - if (i instanceof Instructions.OutputInstruction) { | 179 | + (L2ModificationInstruction) vlanIntruction.get(); |
130 | - Instructions.OutputInstruction out = (Instructions.OutputInstruction) i; | 180 | + |
131 | - return out.port().equals(PortNumber.CONTROLLER); | 181 | + if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) { |
182 | + installUpstreamRules(fwd); | ||
183 | + } else if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) { | ||
184 | + installDownstreamRules(fwd); | ||
185 | + } else { | ||
186 | + log.error("Unknown OLT operation: {}", fwd); | ||
187 | + fail(fwd, ObjectiveError.UNSUPPORTED); | ||
188 | + return; | ||
132 | } | 189 | } |
133 | - return false; | ||
134 | - }); | ||
135 | 190 | ||
136 | - if (isPunt) { | 191 | + pass(fwd); |
192 | + | ||
193 | + } | ||
194 | + | ||
195 | + @Override | ||
196 | + public void next(NextObjective nextObjective) { | ||
197 | + throw new UnsupportedOperationException("OLT does not next hop."); | ||
198 | + } | ||
199 | + | ||
200 | + private void installDownstreamRules(ForwardingObjective fwd) { | ||
201 | + List<Pair<Instruction, Instruction>> vlanOps = | ||
202 | + vlanOps(fwd, | ||
203 | + L2ModificationInstruction.L2SubType.VLAN_POP); | ||
204 | + | ||
205 | + if (vlanOps == null) { | ||
137 | return; | 206 | return; |
138 | } | 207 | } |
139 | 208 | ||
140 | - TrafficSelector selector = fwd.selector(); | 209 | + Instruction output = fetchOutput(fwd, "downstream"); |
141 | - TrafficTreatment treatment = fwd.treatment(); | 210 | + |
211 | + if (output == null) { | ||
212 | + return; | ||
213 | + } | ||
214 | + | ||
215 | + Pair<Instruction, Instruction> popAndRewrite = vlanOps.remove(0); | ||
216 | + | ||
217 | + FlowRule.Builder inner = DefaultFlowRule.builder() | ||
218 | + .forDevice(deviceId) | ||
219 | + .fromApp(appId) | ||
220 | + .makePermanent() | ||
221 | + .withPriority(fwd.priority()) | ||
222 | + .withSelector(fwd.selector()) | ||
223 | + .withTreatment(buildTreatment(popAndRewrite.getLeft(), | ||
224 | + Instructions.transition(QQ_TABLE))); | ||
225 | + PortCriterion inPort = (PortCriterion) | ||
226 | + fwd.selector().getCriterion(Criterion.Type.IN_PORT); | ||
227 | + | ||
228 | + FlowRule.Builder outer = DefaultFlowRule.builder() | ||
229 | + .forDevice(deviceId) | ||
230 | + .fromApp(appId) | ||
231 | + .forTable(QQ_TABLE) | ||
232 | + .makePermanent() | ||
233 | + .withPriority(fwd.priority()) | ||
234 | + .withSelector(buildSelector(inPort)) | ||
235 | + .withTreatment(buildTreatment(popAndRewrite.getRight(), | ||
236 | + output)); | ||
237 | + | ||
238 | + applyRules(fwd, inner, outer); | ||
239 | + | ||
240 | + } | ||
241 | + | ||
242 | + private void installUpstreamRules(ForwardingObjective fwd) { | ||
243 | + List<Pair<Instruction, Instruction>> vlanOps = | ||
244 | + vlanOps(fwd, | ||
245 | + L2ModificationInstruction.L2SubType.VLAN_PUSH); | ||
246 | + | ||
247 | + if (vlanOps == null) { | ||
248 | + return; | ||
249 | + } | ||
250 | + | ||
251 | + Instruction output = fetchOutput(fwd, "upstream"); | ||
252 | + | ||
253 | + if (output == null) { | ||
254 | + return; | ||
255 | + } | ||
256 | + | ||
257 | + Pair<Instruction, Instruction> innerPair = vlanOps.remove(0); | ||
258 | + | ||
259 | + Pair<Instruction, Instruction> outerPair = vlanOps.remove(0); | ||
260 | + | ||
261 | + FlowRule.Builder inner = DefaultFlowRule.builder() | ||
262 | + .forDevice(deviceId) | ||
263 | + .fromApp(appId) | ||
264 | + .makePermanent() | ||
265 | + .withPriority(fwd.priority()) | ||
266 | + .withSelector(fwd.selector()) | ||
267 | + .withTreatment(buildTreatment(innerPair.getRight(), | ||
268 | + Instructions.transition(QQ_TABLE))); | ||
269 | + | ||
270 | + PortCriterion inPort = (PortCriterion) | ||
271 | + fwd.selector().getCriterion(Criterion.Type.IN_PORT); | ||
272 | + | ||
273 | + VlanId cVlanId = ((L2ModificationInstruction.ModVlanIdInstruction) | ||
274 | + innerPair.getRight()).vlanId(); | ||
142 | 275 | ||
143 | - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | 276 | + FlowRule.Builder outer = DefaultFlowRule.builder() |
144 | .forDevice(deviceId) | 277 | .forDevice(deviceId) |
278 | + .fromApp(appId) | ||
279 | + .forTable(QQ_TABLE) | ||
280 | + .makePermanent() | ||
281 | + .withPriority(fwd.priority()) | ||
282 | + .withSelector(buildSelector(inPort, | ||
283 | + Criteria.matchVlanId(cVlanId))) | ||
284 | + .withTreatment(buildTreatment(outerPair.getLeft(), | ||
285 | + outerPair.getRight(), | ||
286 | + output)); | ||
287 | + | ||
288 | + applyRules(fwd, inner, outer); | ||
289 | + | ||
290 | + } | ||
291 | + | ||
292 | + private Instruction fetchOutput(ForwardingObjective fwd, String direction) { | ||
293 | + Instruction output = fwd.treatment().allInstructions().stream() | ||
294 | + .filter(i -> i.type() == Instruction.Type.OUTPUT) | ||
295 | + .findFirst().orElse(null); | ||
296 | + | ||
297 | + if (output == null) { | ||
298 | + log.error("OLT {} rule has no output", direction); | ||
299 | + fail(fwd, ObjectiveError.BADPARAMS); | ||
300 | + return null; | ||
301 | + } | ||
302 | + return output; | ||
303 | + } | ||
304 | + | ||
305 | + private List<Pair<Instruction, Instruction>> vlanOps(ForwardingObjective fwd, | ||
306 | + L2ModificationInstruction.L2SubType type) { | ||
307 | + | ||
308 | + List<Pair<Instruction, Instruction>> vlanOps = findVlanOps( | ||
309 | + fwd.treatment().allInstructions(), type); | ||
310 | + | ||
311 | + if (vlanOps == null) { | ||
312 | + String direction = type == L2ModificationInstruction.L2SubType.VLAN_POP | ||
313 | + ? "downstream" : "upstream"; | ||
314 | + log.error("Missing vlan operations in {} forwarding: {}", direction, fwd); | ||
315 | + fail(fwd, ObjectiveError.BADPARAMS); | ||
316 | + return null; | ||
317 | + } | ||
318 | + return vlanOps; | ||
319 | + } | ||
320 | + | ||
321 | + | ||
322 | + private List<Pair<Instruction, Instruction>> findVlanOps(List<Instruction> instructions, | ||
323 | + L2ModificationInstruction.L2SubType type) { | ||
324 | + | ||
325 | + List<Instruction> vlanPushs = findL2Instructions( | ||
326 | + type, | ||
327 | + instructions); | ||
328 | + List<Instruction> vlanSets = findL2Instructions( | ||
329 | + L2ModificationInstruction.L2SubType.VLAN_ID, | ||
330 | + instructions); | ||
331 | + | ||
332 | + if (vlanPushs.size() != vlanSets.size()) { | ||
333 | + return null; | ||
334 | + } | ||
335 | + | ||
336 | + List<Pair<Instruction, Instruction>> pairs = Lists.newArrayList(); | ||
337 | + | ||
338 | + for (int i = 0; i < vlanPushs.size(); i++) { | ||
339 | + pairs.add(new ImmutablePair<>(vlanPushs.get(i), vlanSets.get(i))); | ||
340 | + } | ||
341 | + return pairs; | ||
342 | + } | ||
343 | + | ||
344 | + private List<Instruction> findL2Instructions(L2ModificationInstruction.L2SubType subType, | ||
345 | + List<Instruction> actions) { | ||
346 | + return actions.stream() | ||
347 | + .filter(i -> i.type() == Instruction.Type.L2MODIFICATION) | ||
348 | + .filter(i -> ((L2ModificationInstruction) i).subtype() == subType) | ||
349 | + .collect(Collectors.toList()); | ||
350 | + } | ||
351 | + | ||
352 | + private void provisionEapol(FilteringObjective filter, | ||
353 | + EthTypeCriterion ethType, | ||
354 | + Instructions.OutputInstruction output) { | ||
355 | + | ||
356 | + TrafficSelector selector = buildSelector(filter.key(), ethType); | ||
357 | + TrafficTreatment treatment = buildTreatment(output); | ||
358 | + buildAndApplyRule(filter, selector, treatment); | ||
359 | + | ||
360 | + } | ||
361 | + | ||
362 | + private void provisionIGMP(FilteringObjective filter, EthTypeCriterion ethType, | ||
363 | + IPProtocolCriterion ipProto, | ||
364 | + Instructions.OutputInstruction output) { | ||
365 | + TrafficSelector selector = buildSelector(filter.key(), ethType, ipProto); | ||
366 | + TrafficTreatment treatment = buildTreatment(output); | ||
367 | + buildAndApplyRule(filter, selector, treatment); | ||
368 | + } | ||
369 | + | ||
370 | + private void buildAndApplyRule(FilteringObjective filter, TrafficSelector selector, | ||
371 | + TrafficTreatment treatment) { | ||
372 | + FlowRule rule = DefaultFlowRule.builder() | ||
373 | + .forDevice(deviceId) | ||
374 | + .forTable(0) | ||
375 | + .fromApp(filter.appId()) | ||
376 | + .makePermanent() | ||
145 | .withSelector(selector) | 377 | .withSelector(selector) |
146 | .withTreatment(treatment) | 378 | .withTreatment(treatment) |
147 | - .fromApp(fwd.appId()) | 379 | + .build(); |
148 | - .withPriority(fwd.priority()); | ||
149 | 380 | ||
150 | - if (fwd.permanent()) { | 381 | + FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder(); |
151 | - ruleBuilder.makePermanent(); | 382 | + |
152 | - } else { | 383 | + switch (filter.type()) { |
153 | - ruleBuilder.makeTemporary(fwd.timeout()); | 384 | + case PERMIT: |
385 | + opsBuilder.add(rule); | ||
386 | + break; | ||
387 | + case DENY: | ||
388 | + opsBuilder.remove(rule); | ||
389 | + break; | ||
390 | + default: | ||
391 | + log.warn("Unknown filter type : {}", filter.type()); | ||
392 | + fail(filter, ObjectiveError.UNSUPPORTED); | ||
154 | } | 393 | } |
155 | 394 | ||
395 | + applyFlowRules(opsBuilder, filter); | ||
396 | + } | ||
397 | + | ||
398 | + private void applyRules(ForwardingObjective fwd, | ||
399 | + FlowRule.Builder inner, FlowRule.Builder outer) { | ||
400 | + FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); | ||
156 | switch (fwd.op()) { | 401 | switch (fwd.op()) { |
157 | case ADD: | 402 | case ADD: |
158 | - flowBuilder.add(ruleBuilder.build()); | 403 | + builder.add(inner.build()).add(outer.build()); |
159 | break; | 404 | break; |
160 | case REMOVE: | 405 | case REMOVE: |
161 | - flowBuilder.remove(ruleBuilder.build()); | 406 | + builder.remove(inner.build()).remove(outer.build()); |
407 | + break; | ||
408 | + case ADD_TO_EXISTING: | ||
409 | + break; | ||
410 | + case REMOVE_FROM_EXISTING: | ||
162 | break; | 411 | break; |
163 | default: | 412 | default: |
164 | - log.warn("Unknown operation {}", fwd.op()); | 413 | + log.warn("Unknown forwarding operation: {}", fwd.op()); |
414 | + } | ||
415 | + | ||
416 | + applyFlowRules(builder, fwd); | ||
165 | } | 417 | } |
166 | 418 | ||
167 | - flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() { | 419 | + private void applyFlowRules(FlowRuleOperations.Builder builder, |
420 | + Objective objective) { | ||
421 | + flowRuleService.apply(builder.build(new FlowRuleOperationsContext() { | ||
168 | @Override | 422 | @Override |
169 | public void onSuccess(FlowRuleOperations ops) { | 423 | public void onSuccess(FlowRuleOperations ops) { |
170 | - if (fwd.context().isPresent()) { | 424 | + pass(objective); |
171 | - fwd.context().get().onSuccess(fwd); | ||
172 | - } | ||
173 | } | 425 | } |
174 | 426 | ||
175 | @Override | 427 | @Override |
176 | public void onError(FlowRuleOperations ops) { | 428 | public void onError(FlowRuleOperations ops) { |
177 | - if (fwd.context().isPresent()) { | 429 | + fail(objective, ObjectiveError.FLOWINSTALLATIONFAILED); |
178 | - fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); | ||
179 | - } | ||
180 | } | 430 | } |
181 | })); | 431 | })); |
182 | } | 432 | } |
183 | 433 | ||
184 | - @Override | 434 | + private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) { |
185 | - public void next(NextObjective nextObjective) { | 435 | + return criteria.stream() |
186 | - throw new UnsupportedOperationException("OLT does not next hop."); | 436 | + .filter(c -> c.type().equals(Criterion.Type.ETH_TYPE)) |
437 | + .limit(1) | ||
438 | + .findFirst().orElse(null); | ||
439 | + } | ||
440 | + | ||
441 | + private TrafficSelector buildSelector(Criterion... criteria) { | ||
442 | + | ||
443 | + | ||
444 | + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); | ||
445 | + | ||
446 | + for (Criterion c : criteria) { | ||
447 | + sBuilder.add(c); | ||
448 | + } | ||
449 | + | ||
450 | + return sBuilder.build(); | ||
451 | + } | ||
452 | + | ||
453 | + private TrafficTreatment buildTreatment(Instruction... instructions) { | ||
454 | + | ||
455 | + | ||
456 | + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | ||
457 | + | ||
458 | + for (Instruction i : instructions) { | ||
459 | + tBuilder.add(i); | ||
460 | + } | ||
461 | + | ||
462 | + return tBuilder.build(); | ||
463 | + } | ||
464 | + | ||
465 | + | ||
466 | + private void fail(Objective obj, ObjectiveError error) { | ||
467 | + if (obj.context().isPresent()) { | ||
468 | + obj.context().get().onError(obj, error); | ||
469 | + } | ||
470 | + } | ||
471 | + | ||
472 | + private void pass(Objective obj) { | ||
473 | + if (obj.context().isPresent()) { | ||
474 | + obj.context().get().onSuccess(obj); | ||
475 | + } | ||
187 | } | 476 | } |
188 | 477 | ||
189 | /** | 478 | /** | ... | ... |
-
Please register or login to post a comment