| /* |
| * Copyright 2015-present Open Networking Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.net.flowobjective.impl.composition; |
| |
| import org.onosproject.net.flowobjective.FilteringObjective; |
| import org.onosproject.net.flowobjective.ForwardingObjective; |
| import org.onosproject.net.flowobjective.NextObjective; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| /** |
| * Provides a policy tree to store all flow tables for each device. |
| * |
| * Note: This class uses in-memory structures and is not yet distributed. |
| */ |
| public class FlowObjectiveCompositionTree { |
| |
| FlowObjectiveCompositionManager.PolicyOperator operator; |
| FlowObjectiveCompositionTree leftChild; |
| FlowObjectiveCompositionTree rightChild; |
| protected short applicationId; |
| protected FilterTable filterTable; |
| protected ForwardTable forwardTable; |
| protected NextTable nextTable; |
| |
| protected int priorityMultiplier; |
| protected int priorityAddend; |
| |
| public FlowObjectiveCompositionTree(short applicationId) { |
| this.operator = FlowObjectiveCompositionManager.PolicyOperator.Application; |
| this.leftChild = null; |
| this.rightChild = null; |
| this.applicationId = applicationId; |
| this.filterTable = new FilterTable(); |
| this.forwardTable = new ForwardTable(); |
| this.nextTable = new NextTable(); |
| this.priorityMultiplier = 10; |
| this.priorityAddend = 10; |
| } |
| |
| public FlowObjectiveCompositionTree(Character ch) { |
| switch (ch) { |
| case '+': |
| this.operator = FlowObjectiveCompositionManager.PolicyOperator.Parallel; |
| break; |
| case '>': |
| this.operator = FlowObjectiveCompositionManager.PolicyOperator.Sequential; |
| break; |
| case '/': |
| this.operator = FlowObjectiveCompositionManager.PolicyOperator.Override; |
| break; |
| default: |
| this.operator = FlowObjectiveCompositionManager.PolicyOperator.Application; |
| break; |
| } |
| this.leftChild = null; |
| this.rightChild = null; |
| this.applicationId = (short) -1; |
| this.filterTable = new FilterTable(); |
| this.forwardTable = new ForwardTable(); |
| this.nextTable = new NextTable(); |
| this.priorityMultiplier = 10; |
| this.priorityAddend = 10; |
| } |
| |
| protected List<FilteringObjective> updateFilter(FilteringObjective filteringObjective) { |
| switch (this.operator) { |
| case Parallel: |
| return updateFilterParallel(filteringObjective); |
| case Sequential: |
| return updateFilterSequential(filteringObjective); |
| case Override: |
| return updateFilterOverride(filteringObjective); |
| case Application: |
| if (filteringObjective.appId().id() == this.applicationId) { |
| return this.filterTable.updateFilter(filteringObjective); |
| } else { |
| return new ArrayList<>(); |
| } |
| default: |
| return new ArrayList<>(); |
| } |
| } |
| |
| // Parallel composition: the filter set is the union of the children |
| protected List<FilteringObjective> updateFilterParallel(FilteringObjective filteringObjective) { |
| List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective); |
| List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective); |
| |
| List<FilteringObjective> updates = new ArrayList<>(); |
| updates.addAll(leftUpdates); |
| updates.addAll(rightUpdates); |
| |
| return this.filterTable.updateFilter(updates); |
| } |
| |
| // Sequential composition: the filter set is the filter set of the left child |
| protected List<FilteringObjective> updateFilterSequential(FilteringObjective filteringObjective) { |
| List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective); |
| List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective); |
| return this.filterTable.updateFilter(leftUpdates); |
| } |
| |
| // Override composition: the filter set is the filter set of the left child |
| protected List<FilteringObjective> updateFilterOverride(FilteringObjective filteringObjective) { |
| List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective); |
| List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective); |
| return this.filterTable.updateFilter(leftUpdates); |
| } |
| |
| public List<ForwardingObjective> updateForward(ForwardingObjective forwardingObjective) { |
| return this.updateForwardNode(forwardingObjective).toForwardingObjectiveList(); |
| } |
| |
| public ForwardUpdateTable updateForwardNode(ForwardingObjective forwardingObjective) { |
| switch (this.operator) { |
| case Parallel: |
| case Sequential: |
| case Override: |
| return updateForwardComposition(forwardingObjective); |
| case Application: |
| if (forwardingObjective.appId().id() == this.applicationId) { |
| return this.forwardTable.updateForward(forwardingObjective); |
| } else { |
| return (new ForwardUpdateTable()); |
| } |
| default: |
| return (new ForwardUpdateTable()); |
| } |
| } |
| |
| protected ForwardUpdateTable updateForwardComposition(ForwardingObjective forwardingObjective) { |
| ForwardUpdateTable leftUpdates = this.leftChild.updateForwardNode(forwardingObjective); |
| ForwardUpdateTable rightUpdates = this.rightChild.updateForwardNode(forwardingObjective); |
| |
| List<ForwardingObjective> addUpdates = new ArrayList<>(); |
| List<ForwardingObjective> removeUpdates = new ArrayList<>(); |
| // Handle ADD |
| if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel |
| || this.operator == FlowObjectiveCompositionManager.PolicyOperator.Sequential) { |
| for (ForwardingObjective fo1 : leftUpdates.addObjectives) { |
| for (ForwardingObjective fo2 : this.rightChild.forwardTable.getForwardingObjectives()) { |
| ForwardingObjective composedFo = null; |
| if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel) { |
| composedFo = FlowObjectiveCompositionUtil.composeParallel(fo1, fo2); |
| } else { |
| composedFo = FlowObjectiveCompositionUtil.composeSequential(fo1, fo2, this.priorityMultiplier); |
| } |
| if (composedFo != null) { |
| addUpdates.add(composedFo); |
| this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo1, composedFo); |
| this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo2, composedFo); |
| } |
| } |
| } |
| Collection<ForwardingObjective> leftTableWithoutAdd = FlowObjectiveCompositionUtil |
| .minusForwardingObjectives(this.leftChild.forwardTable.getForwardingObjectives(), |
| leftUpdates.addObjectives); |
| for (ForwardingObjective fo1 : leftTableWithoutAdd) { |
| for (ForwardingObjective fo2 : rightUpdates.addObjectives) { |
| ForwardingObjective composedFo = null; |
| if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel) { |
| composedFo = FlowObjectiveCompositionUtil.composeParallel(fo1, fo2); |
| } else { |
| composedFo = FlowObjectiveCompositionUtil.composeSequential(fo1, fo2, this.priorityMultiplier); |
| } |
| if (composedFo != null) { |
| addUpdates.add(composedFo); |
| this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo1, composedFo); |
| this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo2, composedFo); |
| } |
| } |
| } |
| } else { |
| for (ForwardingObjective fo : leftUpdates.addObjectives) { |
| ForwardingObjective composedFo = FlowObjectiveCompositionUtil.composeOverride(fo, this.priorityAddend); |
| addUpdates.add(composedFo); |
| this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo, composedFo); |
| } |
| for (ForwardingObjective fo : rightUpdates.addObjectives) { |
| ForwardingObjective composedFo = FlowObjectiveCompositionUtil.composeOverride(fo, 0); |
| addUpdates.add(composedFo); |
| this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo, composedFo); |
| } |
| } |
| |
| // Handle REMOVE |
| for (ForwardingObjective fo : leftUpdates.removeObjectives) { |
| List<ForwardingObjective> fos = this.leftChild.forwardTable |
| .getGeneratedParentForwardingObjectiveForRemove(fo); |
| removeUpdates.addAll(fos); |
| } |
| this.leftChild.forwardTable.deleteGeneratedParentForwardingObjective(leftUpdates.removeObjectives); |
| for (ForwardingObjective fo : rightUpdates.removeObjectives) { |
| List<ForwardingObjective> fos = this.rightChild.forwardTable |
| .getGeneratedParentForwardingObjectiveForRemove(fo); |
| removeUpdates.addAll(fos); |
| } |
| this.rightChild.forwardTable.deleteGeneratedParentForwardingObjective(rightUpdates.removeObjectives); |
| |
| ForwardUpdateTable updates = new ForwardUpdateTable(); |
| updates.addUpdateTable(this.forwardTable.updateForward(addUpdates)); |
| updates.addUpdateTable(this.forwardTable.updateForward(removeUpdates)); |
| return updates; |
| } |
| |
| public List<NextObjective> updateNext(NextObjective nextObjective) { |
| switch (this.operator) { |
| case Parallel: |
| case Sequential: |
| case Override: |
| return updateNextComposition(nextObjective); |
| case Application: |
| if (nextObjective.appId().id() == this.applicationId) { |
| return this.nextTable.updateNext(nextObjective); |
| } else { |
| return new ArrayList<>(); |
| } |
| default: |
| return new ArrayList<>(); |
| } |
| } |
| |
| // Next: the union of the children |
| protected List<NextObjective> updateNextComposition(NextObjective nextObjective) { |
| List<NextObjective> leftUpdates = this.leftChild.updateNext(nextObjective); |
| List<NextObjective> rightUpdates = this.rightChild.updateNext(nextObjective); |
| |
| List<NextObjective> updates = new ArrayList<>(); |
| updates.addAll(leftUpdates); |
| updates.addAll(rightUpdates); |
| |
| return this.nextTable.updateNext(updates); |
| } |
| |
| @Override |
| public String toString() { |
| String str = null; |
| switch (this.operator) { |
| case Parallel: |
| str = "(" + this.leftChild + "+" + this.rightChild + ")"; |
| break; |
| case Sequential: |
| str = "(" + this.leftChild + ">" + this.rightChild + ")"; |
| break; |
| case Override: |
| str = "(" + this.leftChild + "/" + this.rightChild + ")"; |
| break; |
| default: |
| str = " " + applicationId + " "; |
| break; |
| } |
| return str; |
| } |
| |
| } |