blob: 33ffeac178ea4d96580cf48293c22abfe482b827 [file] [log] [blame]
Carmelo Casconeb5324e72018-11-25 02:26:32 -08001/*
2 * Copyright 2017-present Open Networking Foundation
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.pipelines.fabric.pipeliner;
18
19import com.google.common.base.MoreObjects;
20import com.google.common.collect.ImmutableMap;
21import com.google.common.collect.Maps;
22import org.onosproject.net.flow.FlowId;
23import org.onosproject.net.flow.FlowRule;
24import org.onosproject.net.flowobjective.ObjectiveError;
25import org.onosproject.net.group.GroupDescription;
26
27import java.util.Collection;
28import java.util.Collections;
29import java.util.Map;
30import java.util.Objects;
31import java.util.Optional;
32
33import static com.google.common.base.Preconditions.checkNotNull;
34import static java.lang.String.format;
35
36/**
37 * Result of a pipeliner translation from an objective to flows and groups.
38 */
39final class ObjectiveTranslation {
40
41 private final ImmutableMap<FlowId, FlowRule> flowRules;
42 private final ImmutableMap<Integer, GroupDescription> groups;
43 private final ObjectiveError error;
44
45 private ObjectiveTranslation(Map<FlowId, FlowRule> flowRules,
46 Map<Integer, GroupDescription> groups,
47 ObjectiveError error) {
48 this.flowRules = ImmutableMap.copyOf(flowRules);
49 this.groups = ImmutableMap.copyOf(groups);
50 this.error = error;
51 }
52
53 /**
54 * Returns flow rules of this translation.
55 *
56 * @return flow rules
57 */
58 Collection<FlowRule> flowRules() {
59 return flowRules.values();
60 }
61
62 /**
63 * Returns groups of this translation.
64 *
65 * @return groups
66 */
67 Collection<GroupDescription> groups() {
68 return groups.values();
69 }
70
71 /**
72 * Returns the error of this translation, is any.
73 *
74 * @return optional error
75 */
76 Optional<ObjectiveError> error() {
77 return Optional.ofNullable(error);
78 }
79
80 /**
81 * Creates a new builder.
82 *
83 * @return the builder
84 */
85 static Builder builder() {
86 return new Builder();
87 }
88
89 /**
90 * Creates a new translation that signals the given error.
91 *
92 * @param error objective error
93 * @return new objective translation
94 */
95 static ObjectiveTranslation ofError(ObjectiveError error) {
96 checkNotNull(error);
97 return new ObjectiveTranslation(
98 Collections.emptyMap(), Collections.emptyMap(), error);
99 }
100
101 @Override
102 public String toString() {
103 return MoreObjects.toStringHelper(this)
104 .add("flowRules", flowRules)
105 .add("groups", groups)
106 .add("error", error)
107 .toString();
108 }
109
110 @Override
111 public int hashCode() {
112 return Objects.hash(flowRules, groups, error);
113 }
114
115 @Override
116 public boolean equals(Object obj) {
117 if (this == obj) {
118 return true;
119 }
120 if (obj == null || getClass() != obj.getClass()) {
121 return false;
122 }
123 final ObjectiveTranslation other = (ObjectiveTranslation) obj;
124 return flowRulesExactMatch(other.flowRules)
125 && Objects.equals(this.groups, other.groups)
126 && Objects.equals(this.error, other.error);
127 }
128
129 private boolean flowRulesExactMatch(Map<FlowId, FlowRule> otherFlowRules) {
130 if (otherFlowRules == null || otherFlowRules.size() != this.flowRules.size()) {
131 return false;
132 }
133 return this.flowRules.values().stream()
134 .allMatch(f -> otherFlowRules.containsKey(f.id())
135 && otherFlowRules.get(f.id()).exactMatch(f));
136 }
137
138 /**
139 * Builder for ObjectiveTranslation. This implementation checks that flow
140 * and groups are not added when an existing one with same ID (FlowId or
141 * GroupId) has already been added.
142 */
143 static final class Builder {
144
145 private final Map<FlowId, FlowRule> flowRules = Maps.newHashMap();
146 private final Map<Integer, GroupDescription> groups = Maps.newHashMap();
147
148 // Hide default constructor
149 private Builder() {
150 }
151
152 /**
153 * Adds a flow rule to this translation.
154 *
155 * @param flowRule flow rule
156 * @return this
157 * @throws FabricPipelinerException if a FlowRule with same FlowId
158 * already exists in this translation
159 */
160 Builder addFlowRule(FlowRule flowRule)
161 throws FabricPipelinerException {
162 checkNotNull(flowRule);
163 if (flowRules.containsKey(flowRule.id())) {
164 final FlowRule existingFlowRule = flowRules.get(flowRule.id());
165 if (!existingFlowRule.exactMatch(flowRule)) {
166 throw new FabricPipelinerException(format(
167 "Another FlowRule with same ID has already been " +
168 "added to this translation: existing=%s, new=%s",
169 existingFlowRule, flowRule));
170 }
171 }
172 flowRules.put(flowRule.id(), flowRule);
173 return this;
174 }
175
176 /**
177 * Adds group to this translation.
178 *
179 * @param group group
180 * @return this
181 * @throws FabricPipelinerException if a FlowRule with same GroupId
182 * already exists in this translation
183 */
184 Builder addGroup(GroupDescription group)
185 throws FabricPipelinerException {
186 checkNotNull(group);
187 if (groups.containsKey(group.givenGroupId())) {
188 final GroupDescription existingGroup = groups.get(group.givenGroupId());
189 if (!existingGroup.equals(group)) {
190 throw new FabricPipelinerException(format(
191 "Another Group with same ID has already been " +
192 "added to this translation: existing=%s, new=%s",
193 existingGroup, group));
194 }
195 }
196 groups.put(group.givenGroupId(), group);
197 return this;
198 }
199
200 /**
201 * Creates ane translation.
202 *
203 * @return translation instance
204 */
205 ObjectiveTranslation build() {
206 return new ObjectiveTranslation(flowRules, groups, null);
207 }
208 }
209}