Add support for vlan based intents in the Corsa driver
Changes: - Improves processSpecific in AbstractCorsaPipeline in order to support Intents without an explicit match on the Ethertype; - Implements vlan based circuits in CorsaPipelineV3 through the management of the FwdObjective without Treatment; - Distinguish Groups from simple actions; - Corsa group are identified using the actions of the treatment; - handling of the pending next similar to DefaultSingleTablePipeline Change-Id: Iff0f70d56c64193524c6640f31ffb3f5629499dc
Showing
3 changed files
with
203 additions
and
28 deletions
| ... | @@ -93,14 +93,14 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp | ... | @@ -93,14 +93,14 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp |
| 93 | private ServiceDirectory serviceDirectory; | 93 | private ServiceDirectory serviceDirectory; |
| 94 | protected FlowRuleService flowRuleService; | 94 | protected FlowRuleService flowRuleService; |
| 95 | private CoreService coreService; | 95 | private CoreService coreService; |
| 96 | - private GroupService groupService; | 96 | + protected GroupService groupService; |
| 97 | protected MeterService meterService; | 97 | protected MeterService meterService; |
| 98 | - private FlowObjectiveStore flowObjectiveStore; | 98 | + protected FlowObjectiveStore flowObjectiveStore; |
| 99 | protected DeviceId deviceId; | 99 | protected DeviceId deviceId; |
| 100 | protected ApplicationId appId; | 100 | protected ApplicationId appId; |
| 101 | protected DeviceService deviceService; | 101 | protected DeviceService deviceService; |
| 102 | 102 | ||
| 103 | - private KryoNamespace appKryo = new KryoNamespace.Builder() | 103 | + protected KryoNamespace appKryo = new KryoNamespace.Builder() |
| 104 | .register(GroupKey.class) | 104 | .register(GroupKey.class) |
| 105 | .register(DefaultGroupKey.class) | 105 | .register(DefaultGroupKey.class) |
| 106 | .register(CorsaGroup.class) | 106 | .register(CorsaGroup.class) |
| ... | @@ -108,6 +108,8 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp | ... | @@ -108,6 +108,8 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp |
| 108 | .build("AbstractCorsaPipeline"); | 108 | .build("AbstractCorsaPipeline"); |
| 109 | 109 | ||
| 110 | private Cache<GroupKey, NextObjective> pendingGroups; | 110 | private Cache<GroupKey, NextObjective> pendingGroups; |
| 111 | + protected Cache<Integer, NextObjective> pendingNext; | ||
| 112 | + | ||
| 111 | 113 | ||
| 112 | private ScheduledExecutorService groupChecker = | 114 | private ScheduledExecutorService groupChecker = |
| 113 | Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", | 115 | Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", |
| ... | @@ -131,6 +133,16 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp | ... | @@ -131,6 +133,16 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp |
| 131 | } | 133 | } |
| 132 | }).build(); | 134 | }).build(); |
| 133 | 135 | ||
| 136 | + pendingNext = CacheBuilder.newBuilder() | ||
| 137 | + .expireAfterWrite(20, TimeUnit.SECONDS) | ||
| 138 | + .removalListener((RemovalNotification<Integer, NextObjective> notification) -> { | ||
| 139 | + if (notification.getCause() == RemovalCause.EXPIRED) { | ||
| 140 | + notification.getValue().context() | ||
| 141 | + .ifPresent(c -> c.onError(notification.getValue(), | ||
| 142 | + ObjectiveError.FLOWINSTALLATIONFAILED)); | ||
| 143 | + } | ||
| 144 | + }).build(); | ||
| 145 | + | ||
| 134 | groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS); | 146 | groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS); |
| 135 | 147 | ||
| 136 | coreService = serviceDirectory.get(CoreService.class); | 148 | coreService = serviceDirectory.get(CoreService.class); |
| ... | @@ -304,6 +316,7 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp | ... | @@ -304,6 +316,7 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp |
| 304 | 316 | ||
| 305 | @Override | 317 | @Override |
| 306 | public void forward(ForwardingObjective fwd) { | 318 | public void forward(ForwardingObjective fwd) { |
| 319 | + | ||
| 307 | Collection<FlowRule> rules; | 320 | Collection<FlowRule> rules; |
| 308 | FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); | 321 | FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); |
| 309 | 322 | ||
| ... | @@ -354,16 +367,20 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp | ... | @@ -354,16 +367,20 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp |
| 354 | private Collection<FlowRule> processSpecific(ForwardingObjective fwd) { | 367 | private Collection<FlowRule> processSpecific(ForwardingObjective fwd) { |
| 355 | log.debug("Processing specific forwarding objective"); | 368 | log.debug("Processing specific forwarding objective"); |
| 356 | TrafficSelector selector = fwd.selector(); | 369 | TrafficSelector selector = fwd.selector(); |
| 357 | - EthTypeCriterion ethType = | 370 | + EthTypeCriterion ethTypeCriterion = |
| 358 | (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); | 371 | (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); |
| 359 | - if (ethType != null) { | 372 | + VlanIdCriterion vlanIdCriterion = |
| 360 | - short et = ethType.ethType().toShort(); | 373 | + (VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID); |
| 374 | + if (ethTypeCriterion != null) { | ||
| 375 | + short et = ethTypeCriterion.ethType().toShort(); | ||
| 361 | if (et == Ethernet.TYPE_IPV4) { | 376 | if (et == Ethernet.TYPE_IPV4) { |
| 362 | return processSpecificRoute(fwd); | 377 | return processSpecificRoute(fwd); |
| 363 | } else if (et == Ethernet.TYPE_VLAN) { | 378 | } else if (et == Ethernet.TYPE_VLAN) { |
| 364 | /* The ForwardingObjective must specify VLAN ethtype in order to use the Transit Circuit */ | 379 | /* The ForwardingObjective must specify VLAN ethtype in order to use the Transit Circuit */ |
| 365 | return processSpecificSwitch(fwd); | 380 | return processSpecificSwitch(fwd); |
| 366 | } | 381 | } |
| 382 | + } else if (vlanIdCriterion != null) { | ||
| 383 | + return processSpecificSwitch(fwd); | ||
| 367 | } | 384 | } |
| 368 | 385 | ||
| 369 | fail(fwd, ObjectiveError.UNSUPPORTED); | 386 | fail(fwd, ObjectiveError.UNSUPPORTED); |
| ... | @@ -464,6 +481,41 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp | ... | @@ -464,6 +481,41 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp |
| 464 | //Hook for modifying Route flow rule | 481 | //Hook for modifying Route flow rule |
| 465 | protected abstract Builder processSpecificRoutingRule(Builder rb); | 482 | protected abstract Builder processSpecificRoutingRule(Builder rb); |
| 466 | 483 | ||
| 484 | + protected enum CorsaTrafficTreatmentType { | ||
| 485 | + /** | ||
| 486 | + * If the treatment has to be handled as group. | ||
| 487 | + */ | ||
| 488 | + GROUP, | ||
| 489 | + /** | ||
| 490 | + * If the treatment has to be handled as simple set of actions. | ||
| 491 | + */ | ||
| 492 | + ACTIONS | ||
| 493 | + } | ||
| 494 | + | ||
| 495 | + /** | ||
| 496 | + * Helper class to encapsulate both traffic treatment and | ||
| 497 | + * type of treatment. | ||
| 498 | + */ | ||
| 499 | + protected class CorsaTrafficTreatment { | ||
| 500 | + | ||
| 501 | + private CorsaTrafficTreatmentType type; | ||
| 502 | + private TrafficTreatment trafficTreatment; | ||
| 503 | + | ||
| 504 | + public CorsaTrafficTreatment(CorsaTrafficTreatmentType treatmentType, TrafficTreatment trafficTreatment) { | ||
| 505 | + this.type = treatmentType; | ||
| 506 | + this.trafficTreatment = trafficTreatment; | ||
| 507 | + } | ||
| 508 | + | ||
| 509 | + public CorsaTrafficTreatmentType type() { | ||
| 510 | + return type; | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + public TrafficTreatment treatment() { | ||
| 514 | + return trafficTreatment; | ||
| 515 | + } | ||
| 516 | + | ||
| 517 | + } | ||
| 518 | + | ||
| 467 | @Override | 519 | @Override |
| 468 | public void next(NextObjective nextObjective) { | 520 | public void next(NextObjective nextObjective) { |
| 469 | switch (nextObjective.type()) { | 521 | switch (nextObjective.type()) { |
| ... | @@ -471,20 +523,25 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp | ... | @@ -471,20 +523,25 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp |
| 471 | Collection<TrafficTreatment> treatments = nextObjective.next(); | 523 | Collection<TrafficTreatment> treatments = nextObjective.next(); |
| 472 | if (treatments.size() == 1) { | 524 | if (treatments.size() == 1) { |
| 473 | TrafficTreatment treatment = treatments.iterator().next(); | 525 | TrafficTreatment treatment = treatments.iterator().next(); |
| 474 | - treatment = processNextTreatment(treatment); | 526 | + CorsaTrafficTreatment corsaTreatment = processNextTreatment(treatment); |
| 475 | - GroupBucket bucket = | ||
| 476 | - DefaultGroupBucket.createIndirectGroupBucket(treatment); | ||
| 477 | final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id())); | 527 | final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id())); |
| 478 | - GroupDescription groupDescription | 528 | + if (corsaTreatment.type() == CorsaTrafficTreatmentType.GROUP) { |
| 479 | - = new DefaultGroupDescription(deviceId, | 529 | + GroupBucket bucket = DefaultGroupBucket.createIndirectGroupBucket(corsaTreatment.treatment()); |
| 480 | - GroupDescription.Type.INDIRECT, | 530 | + GroupBuckets buckets = new GroupBuckets(Collections.singletonList(bucket)); |
| 481 | - new GroupBuckets(Collections | 531 | + // group id == null, let group service determine group id |
| 482 | - .singletonList(bucket)), | 532 | + GroupDescription groupDescription = new DefaultGroupDescription(deviceId, |
| 483 | - key, | 533 | + GroupDescription.Type.INDIRECT, |
| 484 | - null, // let group service determine group id | 534 | + buckets, |
| 485 | - nextObjective.appId()); | 535 | + key, |
| 486 | - groupService.addGroup(groupDescription); | 536 | + null, |
| 487 | - pendingGroups.put(key, nextObjective); | 537 | + nextObjective.appId()); |
| 538 | + groupService.addGroup(groupDescription); | ||
| 539 | + pendingGroups.put(key, nextObjective); | ||
| 540 | + } else if (corsaTreatment.type() == CorsaTrafficTreatmentType.ACTIONS) { | ||
| 541 | + pendingNext.put(nextObjective.id(), nextObjective); | ||
| 542 | + flowObjectiveStore.putNextGroup(nextObjective.id(), new CorsaGroup(key)); | ||
| 543 | + nextObjective.context().ifPresent(context -> context.onSuccess(nextObjective)); | ||
| 544 | + } | ||
| 488 | } | 545 | } |
| 489 | break; | 546 | break; |
| 490 | case HASHED: | 547 | case HASHED: |
| ... | @@ -501,8 +558,8 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp | ... | @@ -501,8 +558,8 @@ public abstract class AbstractCorsaPipeline extends AbstractHandlerBehaviour imp |
| 501 | } | 558 | } |
| 502 | 559 | ||
| 503 | //Hook for altering the NextObjective treatment | 560 | //Hook for altering the NextObjective treatment |
| 504 | - protected TrafficTreatment processNextTreatment(TrafficTreatment treatment) { | 561 | + protected CorsaTrafficTreatment processNextTreatment(TrafficTreatment treatment) { |
| 505 | - return treatment; | 562 | + return new CorsaTrafficTreatment(CorsaTrafficTreatmentType.GROUP, treatment); |
| 506 | } | 563 | } |
| 507 | 564 | ||
| 508 | //Init helper: Table Miss = Drop | 565 | //Init helper: Table Miss = Drop | ... | ... |
| ... | @@ -30,9 +30,12 @@ import org.onosproject.net.flow.criteria.EthCriterion; | ... | @@ -30,9 +30,12 @@ import org.onosproject.net.flow.criteria.EthCriterion; |
| 30 | import org.onosproject.net.flow.criteria.IPCriterion; | 30 | import org.onosproject.net.flow.criteria.IPCriterion; |
| 31 | import org.onosproject.net.flow.criteria.PortCriterion; | 31 | import org.onosproject.net.flow.criteria.PortCriterion; |
| 32 | import org.onosproject.net.flow.criteria.VlanIdCriterion; | 32 | import org.onosproject.net.flow.criteria.VlanIdCriterion; |
| 33 | +import org.onosproject.net.flow.instructions.Instruction; | ||
| 33 | import org.onosproject.net.flow.instructions.L2ModificationInstruction; | 34 | import org.onosproject.net.flow.instructions.L2ModificationInstruction; |
| 34 | import org.onosproject.net.flowobjective.FilteringObjective; | 35 | import org.onosproject.net.flowobjective.FilteringObjective; |
| 35 | import org.onosproject.net.flowobjective.ForwardingObjective; | 36 | import org.onosproject.net.flowobjective.ForwardingObjective; |
| 37 | +import org.onosproject.net.flowobjective.NextObjective; | ||
| 38 | +import org.onosproject.net.flowobjective.ObjectiveError; | ||
| 36 | import org.onosproject.net.meter.Band; | 39 | import org.onosproject.net.meter.Band; |
| 37 | import org.onosproject.net.meter.DefaultBand; | 40 | import org.onosproject.net.meter.DefaultBand; |
| 38 | import org.onosproject.net.meter.DefaultMeterRequest; | 41 | import org.onosproject.net.meter.DefaultMeterRequest; |
| ... | @@ -69,9 +72,11 @@ public class CorsaPipelineV3 extends AbstractCorsaPipeline { | ... | @@ -69,9 +72,11 @@ public class CorsaPipelineV3 extends AbstractCorsaPipeline { |
| 69 | protected MeterId defaultMeterId = null; | 72 | protected MeterId defaultMeterId = null; |
| 70 | 73 | ||
| 71 | @Override | 74 | @Override |
| 72 | - protected TrafficTreatment processNextTreatment(TrafficTreatment treatment) { | 75 | + protected CorsaTrafficTreatment processNextTreatment(TrafficTreatment treatment) { |
| 73 | TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); | 76 | TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); |
| 74 | 77 | ||
| 78 | + | ||
| 79 | + | ||
| 75 | treatment.immediate().stream() | 80 | treatment.immediate().stream() |
| 76 | .filter(i -> { | 81 | .filter(i -> { |
| 77 | switch (i.type()) { | 82 | switch (i.type()) { |
| ... | @@ -87,7 +92,48 @@ public class CorsaPipelineV3 extends AbstractCorsaPipeline { | ... | @@ -87,7 +92,48 @@ public class CorsaPipelineV3 extends AbstractCorsaPipeline { |
| 87 | return false; | 92 | return false; |
| 88 | } | 93 | } |
| 89 | }).forEach(i -> tb.add(i)); | 94 | }).forEach(i -> tb.add(i)); |
| 90 | - return tb.build(); | 95 | + |
| 96 | + TrafficTreatment t = tb.build(); | ||
| 97 | + | ||
| 98 | + | ||
| 99 | + boolean isPresentModVlanId = false; | ||
| 100 | + boolean isPresentModEthSrc = false; | ||
| 101 | + boolean isPresentModEthDst = false; | ||
| 102 | + boolean isPresentOutpuPort = false; | ||
| 103 | + | ||
| 104 | + for (Instruction instruction : t.immediate()) { | ||
| 105 | + switch (instruction.type()) { | ||
| 106 | + case L2MODIFICATION: | ||
| 107 | + L2ModificationInstruction l2i = (L2ModificationInstruction) instruction; | ||
| 108 | + if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction) { | ||
| 109 | + isPresentModVlanId = true; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + if (l2i instanceof L2ModificationInstruction.ModEtherInstruction) { | ||
| 113 | + L2ModificationInstruction.L2SubType subType = l2i.subtype(); | ||
| 114 | + if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC)) { | ||
| 115 | + isPresentModEthSrc = true; | ||
| 116 | + } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST)) { | ||
| 117 | + isPresentModEthDst = true; | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + case OUTPUT: | ||
| 121 | + isPresentOutpuPort = true; | ||
| 122 | + default: | ||
| 123 | + } | ||
| 124 | + } | ||
| 125 | + CorsaTrafficTreatmentType type = CorsaTrafficTreatmentType.ACTIONS; | ||
| 126 | + /** | ||
| 127 | + * This represents the allowed group for CorsaPipelinev3 | ||
| 128 | + */ | ||
| 129 | + if (isPresentModVlanId && | ||
| 130 | + isPresentModEthSrc && | ||
| 131 | + isPresentModEthDst && | ||
| 132 | + isPresentOutpuPort) { | ||
| 133 | + type = CorsaTrafficTreatmentType.GROUP; | ||
| 134 | + } | ||
| 135 | + CorsaTrafficTreatment corsaTreatment = new CorsaTrafficTreatment(type, t); | ||
| 136 | + return corsaTreatment; | ||
| 91 | } | 137 | } |
| 92 | 138 | ||
| 93 | @Override | 139 | @Override |
| ... | @@ -115,9 +161,37 @@ public class CorsaPipelineV3 extends AbstractCorsaPipeline { | ... | @@ -115,9 +161,37 @@ public class CorsaPipelineV3 extends AbstractCorsaPipeline { |
| 115 | .withPriority(fwd.priority()) | 161 | .withPriority(fwd.priority()) |
| 116 | .forDevice(deviceId) | 162 | .forDevice(deviceId) |
| 117 | .withSelector(filteredSelector) | 163 | .withSelector(filteredSelector) |
| 118 | - .withTreatment(fwd.treatment()) | ||
| 119 | .forTable(VLAN_CIRCUIT_TABLE); | 164 | .forTable(VLAN_CIRCUIT_TABLE); |
| 120 | 165 | ||
| 166 | + if (fwd.treatment() != null) { | ||
| 167 | + ruleBuilder.withTreatment(fwd.treatment()); | ||
| 168 | + } else { | ||
| 169 | + if (fwd.nextId() != null) { | ||
| 170 | + NextObjective nextObjective = pendingNext.getIfPresent(fwd.nextId()); | ||
| 171 | + if (nextObjective != null) { | ||
| 172 | + pendingNext.invalidate(fwd.nextId()); | ||
| 173 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder() | ||
| 174 | + .setVlanPcp((byte) 0) | ||
| 175 | + .setQueue(0) | ||
| 176 | + .meter(defaultMeterId); | ||
| 177 | + nextObjective.next().forEach(trafficTreatment -> { | ||
| 178 | + trafficTreatment.allInstructions().forEach(instruction -> { | ||
| 179 | + treatment.add(instruction); | ||
| 180 | + }); | ||
| 181 | + }); | ||
| 182 | + ruleBuilder.withTreatment(treatment.build()); | ||
| 183 | + } else { | ||
| 184 | + log.warn("The group left!"); | ||
| 185 | + fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING)); | ||
| 186 | + return ImmutableSet.of(); | ||
| 187 | + } | ||
| 188 | + } else { | ||
| 189 | + log.warn("Missing NextObjective ID for ForwardingObjective {}", fwd.id()); | ||
| 190 | + fail(fwd, ObjectiveError.BADPARAMS); | ||
| 191 | + return ImmutableSet.of(); | ||
| 192 | + } | ||
| 193 | + } | ||
| 194 | + | ||
| 121 | if (fwd.permanent()) { | 195 | if (fwd.permanent()) { |
| 122 | ruleBuilder.makePermanent(); | 196 | ruleBuilder.makePermanent(); |
| 123 | } else { | 197 | } else { | ... | ... |
| ... | @@ -29,6 +29,7 @@ import org.onosproject.net.flow.TrafficTreatment; | ... | @@ -29,6 +29,7 @@ import org.onosproject.net.flow.TrafficTreatment; |
| 29 | import org.onosproject.net.flow.criteria.Criterion; | 29 | import org.onosproject.net.flow.criteria.Criterion; |
| 30 | import org.onosproject.net.flow.criteria.IPCriterion; | 30 | import org.onosproject.net.flow.criteria.IPCriterion; |
| 31 | import org.onosproject.net.flow.criteria.IPProtocolCriterion; | 31 | import org.onosproject.net.flow.criteria.IPProtocolCriterion; |
| 32 | +import org.onosproject.net.flow.instructions.Instruction; | ||
| 32 | import org.onosproject.net.flow.instructions.Instructions; | 33 | import org.onosproject.net.flow.instructions.Instructions; |
| 33 | import org.onosproject.net.flow.instructions.L2ModificationInstruction; | 34 | import org.onosproject.net.flow.instructions.L2ModificationInstruction; |
| 34 | import org.onosproject.net.flowobjective.ForwardingObjective; | 35 | import org.onosproject.net.flowobjective.ForwardingObjective; |
| ... | @@ -226,9 +227,8 @@ public class CorsaPipelineV39 extends CorsaPipelineV3 { | ... | @@ -226,9 +227,8 @@ public class CorsaPipelineV39 extends CorsaPipelineV3 { |
| 226 | } | 227 | } |
| 227 | 228 | ||
| 228 | @Override | 229 | @Override |
| 229 | - protected TrafficTreatment processNextTreatment(TrafficTreatment treatment) { | 230 | + protected CorsaTrafficTreatment processNextTreatment(TrafficTreatment treatment) { |
| 230 | TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); | 231 | TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); |
| 231 | - tb.add(Instructions.popVlan()); | ||
| 232 | treatment.immediate().stream() | 232 | treatment.immediate().stream() |
| 233 | .filter(i -> { | 233 | .filter(i -> { |
| 234 | switch (i.type()) { | 234 | switch (i.type()) { |
| ... | @@ -236,7 +236,6 @@ public class CorsaPipelineV39 extends CorsaPipelineV3 { | ... | @@ -236,7 +236,6 @@ public class CorsaPipelineV39 extends CorsaPipelineV3 { |
| 236 | L2ModificationInstruction l2i = (L2ModificationInstruction) i; | 236 | L2ModificationInstruction l2i = (L2ModificationInstruction) i; |
| 237 | if (l2i.subtype() == VLAN_ID || | 237 | if (l2i.subtype() == VLAN_ID || |
| 238 | l2i.subtype() == VLAN_POP || | 238 | l2i.subtype() == VLAN_POP || |
| 239 | - l2i.subtype() == VLAN_POP || | ||
| 240 | l2i.subtype() == ETH_DST || | 239 | l2i.subtype() == ETH_DST || |
| 241 | l2i.subtype() == ETH_SRC) { | 240 | l2i.subtype() == ETH_SRC) { |
| 242 | return true; | 241 | return true; |
| ... | @@ -247,6 +246,51 @@ public class CorsaPipelineV39 extends CorsaPipelineV3 { | ... | @@ -247,6 +246,51 @@ public class CorsaPipelineV39 extends CorsaPipelineV3 { |
| 247 | return false; | 246 | return false; |
| 248 | } | 247 | } |
| 249 | }).forEach(i -> tb.add(i)); | 248 | }).forEach(i -> tb.add(i)); |
| 250 | - return tb.build(); | 249 | + |
| 250 | + TrafficTreatment t = tb.build(); | ||
| 251 | + | ||
| 252 | + boolean isPresentModVlanId = false; | ||
| 253 | + boolean isPresentModEthSrc = false; | ||
| 254 | + boolean isPresentModEthDst = false; | ||
| 255 | + boolean isPresentOutpuPort = false; | ||
| 256 | + | ||
| 257 | + for (Instruction instruction : t.immediate()) { | ||
| 258 | + switch (instruction.type()) { | ||
| 259 | + case L2MODIFICATION: | ||
| 260 | + L2ModificationInstruction l2i = (L2ModificationInstruction) instruction; | ||
| 261 | + if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction) { | ||
| 262 | + isPresentModVlanId = true; | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + if (l2i instanceof L2ModificationInstruction.ModEtherInstruction) { | ||
| 266 | + L2ModificationInstruction.L2SubType subType = l2i.subtype(); | ||
| 267 | + if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC)) { | ||
| 268 | + isPresentModEthSrc = true; | ||
| 269 | + } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST)) { | ||
| 270 | + isPresentModEthDst = true; | ||
| 271 | + } | ||
| 272 | + } | ||
| 273 | + case OUTPUT: | ||
| 274 | + isPresentOutpuPort = true; | ||
| 275 | + default: | ||
| 276 | + } | ||
| 277 | + } | ||
| 278 | + CorsaTrafficTreatmentType type = CorsaTrafficTreatmentType.ACTIONS; | ||
| 279 | + /** | ||
| 280 | + * These are the allowed groups for CorsaPipelinev39 | ||
| 281 | + */ | ||
| 282 | + if (isPresentModVlanId && isPresentModEthSrc && isPresentModEthDst && isPresentOutpuPort) { | ||
| 283 | + type = CorsaTrafficTreatmentType.GROUP; | ||
| 284 | + | ||
| 285 | + } else if ((!isPresentModVlanId && isPresentModEthSrc && isPresentModEthDst && isPresentOutpuPort) || | ||
| 286 | + (!isPresentModVlanId && !isPresentModEthSrc && isPresentModEthDst && isPresentOutpuPort) || | ||
| 287 | + (!isPresentModVlanId && !isPresentModEthSrc && !isPresentModEthDst && isPresentOutpuPort)) { | ||
| 288 | + type = CorsaTrafficTreatmentType.GROUP; | ||
| 289 | + TrafficTreatment.Builder tb2 = DefaultTrafficTreatment.builder(t); | ||
| 290 | + tb2.add(Instructions.popVlan()); | ||
| 291 | + t = tb2.build(); | ||
| 292 | + } | ||
| 293 | + CorsaTrafficTreatment corsaTreatment = new CorsaTrafficTreatment(type, t); | ||
| 294 | + return corsaTreatment; | ||
| 251 | } | 295 | } |
| 252 | } | 296 | } | ... | ... |
-
Please register or login to post a comment