blob: 7701f29cd66cae4cba7f93340d33713fc8989dae [file] [log] [blame]
Pier Ventred48320e2016-08-17 16:25:47 -07001/*
2 * Copyright 2016-present 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 */
16
17package org.onosproject.net.intent.impl.compiler;
18
19import com.google.common.collect.SetMultimap;
Yi Tseng2a81c9d2016-09-14 10:14:24 -070020import com.google.common.collect.Sets;
Pier Ventred48320e2016-08-17 16:25:47 -070021import org.onlab.packet.Ip4Address;
22import org.onlab.packet.IpPrefix;
23import org.onosproject.net.ConnectPoint;
24import org.onosproject.net.DeviceId;
25import org.onosproject.net.Link;
26import org.onosproject.net.PortNumber;
Yi Tseng2a81c9d2016-09-14 10:14:24 -070027import org.onosproject.net.FilteredConnectPoint;
Pier Ventred48320e2016-08-17 16:25:47 -070028import org.onosproject.net.flow.DefaultTrafficSelector;
29import org.onosproject.net.flow.DefaultTrafficTreatment;
30import org.onosproject.net.flow.TrafficSelector;
31import org.onosproject.net.flow.TrafficTreatment;
Yi Tseng2a81c9d2016-09-14 10:14:24 -070032import org.onosproject.net.flow.criteria.Criteria;
33import org.onosproject.net.flow.criteria.Criterion;
34import org.onosproject.net.flow.criteria.MplsCriterion;
35import org.onosproject.net.flow.criteria.TunnelIdCriterion;
36import org.onosproject.net.flow.criteria.VlanIdCriterion;
Pier Ventre27d42572016-08-29 17:37:08 -070037import org.onosproject.net.flow.instructions.Instruction;
Pier Ventred48320e2016-08-17 16:25:47 -070038import org.onosproject.net.flow.instructions.L0ModificationInstruction;
39import org.onosproject.net.flow.instructions.L1ModificationInstruction;
40import org.onosproject.net.flow.instructions.L2ModificationInstruction;
41import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
Pier Ventred48320e2016-08-17 16:25:47 -070042import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
43import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
Yi Tseng2a81c9d2016-09-14 10:14:24 -070044import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
45import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction;
46import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
Pier Ventred48320e2016-08-17 16:25:47 -070047import org.onosproject.net.flow.instructions.L3ModificationInstruction;
Pier Ventred48320e2016-08-17 16:25:47 -070048import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
49import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
Yi Tseng2a81c9d2016-09-14 10:14:24 -070050import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction;
51import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction;
52import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction;
Pier Ventred48320e2016-08-17 16:25:47 -070053import org.onosproject.net.flow.instructions.L4ModificationInstruction;
54import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
55import org.onosproject.net.intent.IntentCompilationException;
56import org.onosproject.net.intent.LinkCollectionIntent;
57
58import java.util.List;
Pier Ventre647138f2016-08-26 17:32:44 -070059import java.util.Optional;
Pier Ventred48320e2016-08-17 16:25:47 -070060import java.util.Set;
61import java.util.stream.Collectors;
62
Yi Tseng2a81c9d2016-09-14 10:14:24 -070063import static org.onosproject.net.flow.criteria.Criterion.Type.MPLS_LABEL;
64import static org.onosproject.net.flow.criteria.Criterion.Type.TUNNEL_ID;
65import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID;
66
67
Pier Ventred48320e2016-08-17 16:25:47 -070068/**
69 * Shared APIs and implementations for Link Collection compilers.
70 */
71public class LinkCollectionCompiler<T> {
72
Yi Tseng2a81c9d2016-09-14 10:14:24 -070073 private static final Set<Criterion.Type> TAG_CRITERION_TYPES =
74 Sets.immutableEnumSet(VLAN_VID, MPLS_LABEL, TUNNEL_ID);
75
Pier Ventred48320e2016-08-17 16:25:47 -070076 /**
77 * Helper class to encapsulate treatment and selector.
78 */
79 protected class ForwardingInstructions {
80
81 private TrafficTreatment trafficTreatment;
82
83 private TrafficSelector trafficSelector;
84
85 public ForwardingInstructions(TrafficTreatment treatment, TrafficSelector selector) {
86
87 this.trafficTreatment = treatment;
88 this.trafficSelector = selector;
89
90 }
91
92 public TrafficTreatment treatment() {
93 return this.trafficTreatment;
94 }
95
96 public TrafficSelector selector() {
97 return this.trafficSelector;
98 }
99
100 }
101
102 /**
Brian O'Connora67f8f22016-09-22 11:13:37 -0700103 * Helper method to compute input and output ports.
Pier Ventred48320e2016-08-17 16:25:47 -0700104 *
105 * @param intent the related intents
106 * @param inputPorts the input ports to compute
107 * @param outputPorts the output ports to compute
108 */
109 protected void computePorts(LinkCollectionIntent intent,
110 SetMultimap<DeviceId, PortNumber> inputPorts,
111 SetMultimap<DeviceId, PortNumber> outputPorts) {
112
113 for (Link link : intent.links()) {
114 inputPorts.put(link.dst().deviceId(), link.dst().port());
115 outputPorts.put(link.src().deviceId(), link.src().port());
116 }
117
118 for (ConnectPoint ingressPoint : intent.ingressPoints()) {
119 inputPorts.put(ingressPoint.deviceId(), ingressPoint.port());
120 }
121
122 for (ConnectPoint egressPoint : intent.egressPoints()) {
123 outputPorts.put(egressPoint.deviceId(), egressPoint.port());
124 }
Pier Ventred48320e2016-08-17 16:25:47 -0700125 }
126
127 /**
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700128 * Gets ingress and egress port number of specific device.
Pier Ventred48320e2016-08-17 16:25:47 -0700129 *
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700130 * @param intent the related
131 * @param deviceId device Id
Pier Ventred48320e2016-08-17 16:25:47 -0700132 * @param ingressPorts the ingress ports to compute
133 * @param egressPorts the egress ports to compute
134 */
135 protected void computePorts(LinkCollectionIntent intent,
136 DeviceId deviceId,
137 Set<PortNumber> ingressPorts,
138 Set<PortNumber> egressPorts) {
139
140 if (!intent.applyTreatmentOnEgress()) {
141 ingressPorts.addAll(intent.ingressPoints().stream()
142 .filter(point -> point.deviceId().equals(deviceId))
143 .map(ConnectPoint::port)
144 .collect(Collectors.toSet()));
145 } else {
146 egressPorts.addAll(intent.egressPoints().stream()
147 .filter(point -> point.deviceId().equals(deviceId))
148 .map(ConnectPoint::port)
149 .collect(Collectors.toSet()));
150 }
151
152 }
153
154 /**
155 * Creates the flows representations.
156 *
157 * @param intent the intent to compile
158 * @param deviceId the affected device
159 * @param inPorts the input ports
160 * @param outPorts the output ports
161 * @return the list of flows representations
162 */
163 protected List<T> createRules(LinkCollectionIntent intent, DeviceId deviceId,
164 Set<PortNumber> inPorts, Set<PortNumber> outPorts) {
165 return null;
166 }
167
168
169 /**
170 * Computes treatment and selector which will be used
171 * in the flow representation (Rule, Objective).
172 *
173 * @param intent the intent to compile
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700174 * @param inPort the input port of this device
Pier Ventre647138f2016-08-26 17:32:44 -0700175 * @param deviceId the current device
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700176 * @param outPorts the output ports of this device
177 * @param ingressPorts intent ingress ports of this device
178 * @param egressPorts intent egress ports of this device
Pier Ventred48320e2016-08-17 16:25:47 -0700179 * @return the forwarding instruction object which encapsulates treatment and selector
180 */
Pier Ventre647138f2016-08-26 17:32:44 -0700181 protected ForwardingInstructions createForwardingInstructions(LinkCollectionIntent intent,
182 PortNumber inPort,
183 DeviceId deviceId,
Pier Ventred48320e2016-08-17 16:25:47 -0700184 Set<PortNumber> outPorts,
185 Set<PortNumber> ingressPorts,
186 Set<PortNumber> egressPorts) {
187
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700188 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
189 TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(intent.selector());
190 selectorBuilder.matchInPort(inPort);
Pier Ventred48320e2016-08-17 16:25:47 -0700191
192 if (!intent.applyTreatmentOnEgress()) {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700193 // FIXME: currently, we assume this intent is compile from mp2sp intent
194 Optional<FilteredConnectPoint> filteredIngressPoint =
195 getFilteredConnectPointFromIntent(deviceId, inPort, intent);
196 Optional<FilteredConnectPoint> filteredEgressPoint =
197 intent.filteredEgressPoints().stream().findFirst();
Pier Ventred48320e2016-08-17 16:25:47 -0700198
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700199 if (filteredIngressPoint.isPresent()) {
200 // Ingress device
201 intent.treatment().allInstructions().stream()
202 .filter(inst -> inst.type() != Instruction.Type.NOACTION)
203 .forEach(treatmentBuilder::add);
204
205 if (filteredEgressPoint.isPresent()) {
206 // Apply selector from ingress point
207 filteredIngressPoint.get()
208 .trafficSelector()
209 .criteria()
210 .forEach(selectorBuilder::add);
211
212 TrafficTreatment forwardingTreatment =
213 forwardingTreatment(filteredIngressPoint.get(),
214 filteredEgressPoint.get());
215
216 forwardingTreatment.allInstructions().stream()
217 .filter(inst -> inst.type() != Instruction.Type.NOACTION)
218 .forEach(treatmentBuilder::add);
Pier Ventre647138f2016-08-26 17:32:44 -0700219 } else {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700220 throw new IntentCompilationException("Can't find filtered connection point");
Pier Ventre647138f2016-08-26 17:32:44 -0700221 }
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700222
Pier Ventred48320e2016-08-17 16:25:47 -0700223 } else {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700224 // Not ingress device, won't apply treatments.
225 // Use selector by treatment from intent.
226 updateBuilder(selectorBuilder, intent.treatment());
227
228 // Selector should be overridden by selector from connect point.
229 if (filteredEgressPoint.isPresent()) {
230 filteredEgressPoint.get()
231 .trafficSelector()
232 .criteria()
233 .forEach(selectorBuilder::add);
234 }
235
Pier Ventred48320e2016-08-17 16:25:47 -0700236 }
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700237
238 outPorts.forEach(treatmentBuilder::setOutput);
239
Pier Ventred48320e2016-08-17 16:25:47 -0700240 } else {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700241 // FIXME: currently, we assume this intent is compile from sp2mp intent
242 Optional<FilteredConnectPoint> filteredIngressPoint =
243 intent.filteredIngressPoints().stream().findFirst();
244
245 if (filteredIngressPoint.isPresent()) {
246 // Apply selector from ingress point
247 filteredIngressPoint.get()
248 .trafficSelector()
249 .criteria()
250 .forEach(selectorBuilder::add);
Pier Ventred48320e2016-08-17 16:25:47 -0700251 } else {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700252 throw new IntentCompilationException(
253 "Filtered connection point for ingress" +
254 "point does not exist");
255 }
256
257 for (PortNumber outPort : outPorts) {
258 Optional<FilteredConnectPoint> filteredEgressPoint =
259 getFilteredConnectPointFromIntent(deviceId, outPort, intent);
260
261 if (filteredEgressPoint.isPresent()) {
262 // Egress port, apply treatment + forwarding treatment
263 intent.treatment().allInstructions().stream()
264 .filter(inst -> inst.type() != Instruction.Type.NOACTION)
265 .forEach(treatmentBuilder::add);
266
267 TrafficTreatment forwardingTreatment =
268 forwardingTreatment(filteredIngressPoint.get(),
269 filteredEgressPoint.get());
270 forwardingTreatment.allInstructions().stream()
271 .filter(inst -> inst.type() != Instruction.Type.NOACTION)
272 .forEach(treatmentBuilder::add);
273 }
274
275 treatmentBuilder.setOutput(outPort);
276
277 }
278
279 }
280
281
282 return new ForwardingInstructions(treatmentBuilder.build(), selectorBuilder.build());
283
284 }
285
286 /**
287 * Get FilteredConnectPoint from LinkCollectionIntent.
288 * @param deviceId device Id for connect point
289 * @param portNumber port number
290 * @param intent source intent
291 * @return filtered connetion point
292 */
293 private Optional<FilteredConnectPoint> getFilteredConnectPointFromIntent(DeviceId deviceId,
294 PortNumber portNumber,
295 LinkCollectionIntent intent) {
296 Set<FilteredConnectPoint> filteredConnectPoints =
297 Sets.union(intent.filteredIngressPoints(), intent.filteredEgressPoints());
298 return filteredConnectPoints.stream()
299 .filter(port -> port.connectPoint().deviceId().equals(deviceId))
300 .filter(port -> port.connectPoint().port().equals(portNumber))
301 .findFirst();
302 }
303
304 /**
305 * Get tag criterion from selector.
306 * The criterion should be one of type in tagCriterionTypes.
307 *
308 * @param selector selector
309 * @return Criterion that matched, if there is no tag criterion, return null
310 */
311 private Criterion getTagCriterion(TrafficSelector selector) {
312 return selector.criteria().stream()
313 .filter(criterion -> TAG_CRITERION_TYPES.contains(criterion.type()))
314 .findFirst()
315 .orElse(Criteria.dummy());
316
317 }
318
319 /**
320 * Compares tag type between ingress and egress point and generate
321 * treatment for egress point of intent.
322 *
323 * @param ingress ingress point for the intent
324 * @param egress egress point for the intent
325 * @return Builder of TrafficTreatment
326 */
327 private TrafficTreatment forwardingTreatment(FilteredConnectPoint ingress,
328 FilteredConnectPoint egress) {
329
330
331 if (ingress.trafficSelector().equals(egress.trafficSelector())) {
332 return DefaultTrafficTreatment.emptyTreatment();
333 }
334
335 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
336
337 /*
338 * "null" means there is no tag for the port
339 * Tag criterion will be null if port is normal connection point
340 */
341 Criterion ingressTagCriterion = getTagCriterion(ingress.trafficSelector());
342 Criterion egressTagCriterion = getTagCriterion(egress.trafficSelector());
343
344 if (ingressTagCriterion.type() != egressTagCriterion.type()) {
345
346 /*
347 * Tag type of ingress port and egress port are different.
348 * Need to remove tag from ingress, then add new tag for egress.
349 * Remove nothing if ingress port use VXLAN or there is no tag
350 * on ingress port.
351 */
352 switch (ingressTagCriterion.type()) {
353 case VLAN_VID:
354 builder.popVlan();
355 break;
356 case MPLS_LABEL:
357 builder.popMpls();
358 break;
359 default:
360 break;
361 }
362
363 /*
364 * Push new tag for egress port.
365 */
366 switch (egressTagCriterion.type()) {
367 case VLAN_VID:
368 builder.pushVlan();
369 break;
370 case MPLS_LABEL:
371 builder.pushMpls();
372 break;
373 default:
374 break;
Pier Ventred48320e2016-08-17 16:25:47 -0700375 }
376 }
377
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700378 switch (egressTagCriterion.type()) {
379 case VLAN_VID:
380 VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) egressTagCriterion;
381 builder.setVlanId(vlanIdCriterion.vlanId());
382 break;
383 case MPLS_LABEL:
384 MplsCriterion mplsCriterion = (MplsCriterion) egressTagCriterion;
385 builder.setMpls(mplsCriterion.label());
386 break;
387 case TUNNEL_ID:
388 TunnelIdCriterion tunnelIdCriterion = (TunnelIdCriterion) egressTagCriterion;
389 builder.setTunnelId(tunnelIdCriterion.tunnelId());
390 break;
391 default:
392 break;
Pier Ventre27d42572016-08-29 17:37:08 -0700393 }
Pier Ventre27d42572016-08-29 17:37:08 -0700394
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700395 return builder.build();
Pier Ventre647138f2016-08-26 17:32:44 -0700396 }
397
398 /**
Pier Ventred48320e2016-08-17 16:25:47 -0700399 * Update the selector builder using a L0 instruction.
400 *
401 * @param builder the builder to update
402 * @param l0instruction the l0 instruction to use
403 */
404 private void updateBuilder(TrafficSelector.Builder builder, L0ModificationInstruction l0instruction) {
405 throw new IntentCompilationException("L0 not supported");
406 }
407
408 /**
409 * Update the selector builder using a L1 instruction.
410 *
411 * @param builder the builder to update
412 * @param l1instruction the l1 instruction to use
413 */
414 private void updateBuilder(TrafficSelector.Builder builder, L1ModificationInstruction l1instruction) {
415 throw new IntentCompilationException("L1 not supported");
416 }
417
418 /**
419 * Update the selector builder using a L2 instruction.
420 *
421 * @param builder the builder to update
422 * @param l2instruction the l2 instruction to use
423 */
424 private void updateBuilder(TrafficSelector.Builder builder, L2ModificationInstruction l2instruction) {
425 switch (l2instruction.subtype()) {
426 case ETH_SRC:
427 case ETH_DST:
428 ModEtherInstruction ethInstr = (ModEtherInstruction) l2instruction;
429 switch (ethInstr.subtype()) {
430 case ETH_SRC:
431 builder.matchEthSrc(ethInstr.mac());
432 break;
433 case ETH_DST:
434 builder.matchEthDst(ethInstr.mac());
435 break;
436 default:
437 throw new IntentCompilationException("Bad eth subtype");
438 }
439 break;
440 case VLAN_ID:
441 ModVlanIdInstruction vlanIdInstr = (ModVlanIdInstruction) l2instruction;
442 builder.matchVlanId(vlanIdInstr.vlanId());
443 break;
444 case VLAN_PUSH:
445 //FIXME
446 break;
447 case VLAN_POP:
448 //TODO how do we handle dropped label? remove the selector?
449 throw new IntentCompilationException("Can't handle pop label");
450 case VLAN_PCP:
451 ModVlanPcpInstruction vlanPcpInstruction = (ModVlanPcpInstruction) l2instruction;
452 builder.matchVlanPcp(vlanPcpInstruction.vlanPcp());
453 break;
454 case MPLS_LABEL:
455 case MPLS_PUSH:
456 //FIXME
457 ModMplsLabelInstruction mplsInstr = (ModMplsLabelInstruction) l2instruction;
458 builder.matchMplsLabel(mplsInstr.label());
459 break;
460 case MPLS_POP:
461 //TODO how do we handle dropped label? remove the selector?
462 throw new IntentCompilationException("Can't handle pop label");
463 case DEC_MPLS_TTL:
464 // no-op
465 break;
466 case MPLS_BOS:
467 ModMplsBosInstruction mplsBosInstr = (ModMplsBosInstruction) l2instruction;
468 builder.matchMplsBos(mplsBosInstr.mplsBos());
469 break;
470 case TUNNEL_ID:
471 ModTunnelIdInstruction tunInstr = (ModTunnelIdInstruction) l2instruction;
472 builder.matchTunnelId(tunInstr.tunnelId());
473 break;
474 default:
475 throw new IntentCompilationException("Unknown L2 Modification instruction");
476 }
477
478 }
479
480 /**
481 * Update the selector builder using a L3 instruction.
482 *
483 * @param builder the builder to update
484 * @param l3instruction the l3 instruction to use
485 */
486 private void updateBuilder(TrafficSelector.Builder builder, L3ModificationInstruction l3instruction) {
487 // TODO check ethernet proto
488 switch (l3instruction.subtype()) {
489 case IPV4_SRC:
490 case IPV4_DST:
491 case IPV6_SRC:
492 case IPV6_DST:
493 ModIPInstruction ipInstr = (ModIPInstruction) l3instruction;
494 // TODO check if ip falls in original prefix
495 IpPrefix prefix = ipInstr.ip().toIpPrefix();
496 switch (ipInstr.subtype()) {
497 case IPV4_SRC:
498 builder.matchIPSrc(prefix);
499 break;
500 case IPV4_DST:
501 builder.matchIPSrc(prefix);
502 break;
503 case IPV6_SRC:
504 builder.matchIPv6Src(prefix);
505 break;
506 case IPV6_DST:
507 builder.matchIPv6Dst(prefix);
508 break;
509 default:
510 throw new IntentCompilationException("Bad type for IP instruction");
511 }
512 break;
513 case IPV6_FLABEL:
514 ModIPv6FlowLabelInstruction ipFlowInstr = (ModIPv6FlowLabelInstruction) l3instruction;
515 builder.matchIPv6FlowLabel(ipFlowInstr.flowLabel());
516 break;
517 case DEC_TTL:
518 // no-op
519 break;
520 case TTL_OUT:
521 // no-op
522 break;
523 case TTL_IN:
524 // no-op
525 break;
526 case ARP_SPA:
527 ModArpIPInstruction arpIpInstr = (ModArpIPInstruction) l3instruction;
528 if (arpIpInstr.ip().isIp4()) {
529 builder.matchArpSpa((Ip4Address) arpIpInstr.ip());
530 } else {
531 throw new IntentCompilationException("IPv6 not supported for ARP");
532 }
533 break;
534 case ARP_SHA:
535 ModArpEthInstruction arpEthInstr = (ModArpEthInstruction) l3instruction;
536 builder.matchArpSha(arpEthInstr.mac());
537 break;
538 case ARP_OP:
539 ModArpOpInstruction arpOpInstr = (ModArpOpInstruction) l3instruction;
540 //FIXME is the long to int cast safe?
541 builder.matchArpOp((int) arpOpInstr.op());
542 break;
543 default:
544 throw new IntentCompilationException("Unknown L3 Modification instruction");
545 }
546 }
547
548 /**
549 * Update the selector builder using a L4 instruction.
550 *
551 * @param builder the builder to update
552 * @param l4instruction the l4 instruction to use
553 */
554 private void updateBuilder(TrafficSelector.Builder builder, L4ModificationInstruction l4instruction) {
555 if (l4instruction instanceof ModTransportPortInstruction) {
556 // TODO check IP proto
557 ModTransportPortInstruction l4mod = (ModTransportPortInstruction) l4instruction;
558 switch (l4mod.subtype()) {
559 case TCP_SRC:
560 builder.matchTcpSrc(l4mod.port());
561 break;
562 case TCP_DST:
563 builder.matchTcpDst(l4mod.port());
564 break;
565 case UDP_SRC:
566 builder.matchUdpSrc(l4mod.port());
567 break;
568 case UDP_DST:
569 builder.matchUdpDst(l4mod.port());
570 break;
571 default:
572 throw new IntentCompilationException("Unknown L4 Modification instruction");
573 }
574 } else {
575 throw new IntentCompilationException("Unknown L4 Modification instruction");
576 }
577 }
578
579 /**
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700580 * Update selector builder by using treatment.
Pier Ventred48320e2016-08-17 16:25:47 -0700581 *
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700582 * @param builder builder to update
583 * @param treatment traffic treatment
Pier Ventred48320e2016-08-17 16:25:47 -0700584 */
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700585 private void updateBuilder(TrafficSelector.Builder builder, TrafficTreatment treatment) {
586
587 treatment.allInstructions().forEach(instruction -> {
588 switch (instruction.type()) {
589 case L0MODIFICATION:
590 updateBuilder(builder, (L0ModificationInstruction) instruction);
591 break;
592 case L1MODIFICATION:
593 updateBuilder(builder, (L1ModificationInstruction) instruction);
594 break;
595 case L2MODIFICATION:
596 updateBuilder(builder, (L2ModificationInstruction) instruction);
597 break;
598 case L3MODIFICATION:
599 updateBuilder(builder, (L3ModificationInstruction) instruction);
600 break;
601 case L4MODIFICATION:
602 updateBuilder(builder, (L4ModificationInstruction) instruction);
603 break;
604 case NOACTION:
605 case OUTPUT:
606 case GROUP:
607 case QUEUE:
608 case TABLE:
609 case METER:
610 case METADATA:
611 case EXTENSION: // TODO is extension no-op or unsupported?
612 // Nothing to do
613 break;
614 default:
615 throw new IntentCompilationException("Unknown instruction type");
616 }
617 });
618
Pier Ventred48320e2016-08-17 16:25:47 -0700619 }
620
621}