blob: 37e5776f19a733fb4906716c17067b5d92db3a42 [file] [log] [blame]
David Glantz05c6f432020-03-19 14:56:12 -05001/*
2 * Copyright 2014-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 */
16package org.onosproject.net.intent.constraint;
17
18import com.google.common.annotations.Beta;
19import com.google.common.collect.ImmutableSet;
20import org.onosproject.net.AnnotationKeys;
21import org.onosproject.net.Link;
22import org.onosproject.net.intent.ResourceContext;
23
24import java.util.Objects;
25import java.util.List;
26
27import static com.google.common.base.MoreObjects.toStringHelper;
28import static com.google.common.base.Preconditions.checkArgument;
29import static com.google.common.base.Preconditions.checkNotNull;
30
31/**
32 * Constraint that evaluates links based on their type.
33 */
34@Beta
35public class TierConstraint extends BooleanConstraint {
36
37 public enum CostType {
38 /**
39 * Configures the constraint to return the same cost (1.0) for any
40 * link that has a valid tier value.
41 */
42 VALID,
43 /**
44 * Configures the constraint to return the tier value as the cost.
45 */
46 TIER,
47 /**
48 * Configures the constraint to return the order the tier value was
49 * added to the list of included tiers on the constraint.
50 */
51 ORDER;
52 }
53
54 private final List<Integer> tiers;
55 private final boolean isInclusive;
56 private final CostType costType;
57
58 /**
59 * Creates a new constraint for requesting connectivity using or avoiding
60 * the specified link tiers.
61 *
62 * @param inclusive indicates whether the given link tiers are to be
63 * permitted or avoided
64 * @param costType defines the model used to calculate the link cost.
65 * @param tiers link tiers
66 */
67 public TierConstraint(boolean inclusive, CostType costType, Integer... tiers) {
68 checkNotNull(tiers, "Link tiers cannot be null");
69 checkArgument(tiers.length > 0, "There must at least one tier");
70 if (costType == CostType.ORDER) {
71 checkArgument(inclusive, "Order is only valid when inclusive=true");
72 }
73 this.tiers = ImmutableSet.copyOf(tiers).asList();
74 this.isInclusive = inclusive;
75 this.costType = costType;
76 }
77
78 /**
79 * Creates a new constraint for requesting connectivity using or avoiding
80 * the specified link tiers. The VALID cost type is used by default.
81 *
82 * @param inclusive indicates whether the given link tiers are to be
83 * permitted or avoided
84 * @param tiers link tiers
85 */
86 public TierConstraint(boolean inclusive, Integer... tiers) {
87 this(inclusive, CostType.VALID, tiers);
88 }
89
90 // Constructor for serialization
91 private TierConstraint() {
92 this.tiers = null;
93 this.isInclusive = false;
94 this.costType = CostType.VALID;
95 }
96
97 // doesn't use LinkResourceService
98 @Override
99 public boolean isValid(Link link, ResourceContext context) {
100 // explicitly call a method not depending on LinkResourceService
101 return isValid(link);
102 }
103
104 private boolean isValid(Link link) {
105 boolean contains = link.annotations().keys().contains(AnnotationKeys.TIER)
106 && tiers.contains(Integer.valueOf(
107 link.annotations().value(AnnotationKeys.TIER)));
108 return isInclusive == contains;
109 }
110
111 // doesn't use LinkResourceService
112 @Override
113 public double cost(Link link, ResourceContext context) {
114 // explicitly call a method not depending on LinkResourceService
115 return cost(link);
116 }
117
118 private double cost(Link link) {
119 double cost = -1.0;
120
121 if (isValid(link)) {
122 Integer tier = new Integer(link.annotations().value(AnnotationKeys.TIER));
123 if (costType == CostType.ORDER) {
124 cost = tiers.indexOf(tier) + 1;
125 } else if (costType == CostType.TIER) {
126 cost = tier;
127 } else {
128 cost = 1.0;
129 }
130 }
131
132 return cost;
133 }
134
135 /**
136 * Returns the set of link tiers.
137 *
138 * @return set of link tiers
139 */
140 public List<Integer> tiers() {
141 return tiers;
142 }
143
144 /**
145 * Indicates if the constraint is inclusive or exclusive.
146 *
147 * @return true if inclusive
148 */
149 public boolean isInclusive() {
150 return isInclusive;
151 }
152
153 /**
154 * Return the cost model used by this constraint.
155 *
156 * @return true if inclusive
157 */
158 public CostType costType() {
159 return costType;
160 }
161
162 @Override
163 public int hashCode() {
164 return Objects.hash(tiers, isInclusive);
165 }
166
167 @Override
168 public boolean equals(Object obj) {
169 if (this == obj) {
170 return true;
171 }
172 if (obj == null || getClass() != obj.getClass()) {
173 return false;
174 }
175 final TierConstraint other = (TierConstraint) obj;
176 return Objects.equals(this.tiers, other.tiers) && Objects.equals(this.isInclusive, other.isInclusive)
177 && Objects.equals(this.costType, other.costType);
178 }
179
180 @Override
181 public String toString() {
182 return toStringHelper(this)
183 .add("inclusive", isInclusive)
184 .add("costType", costType)
185 .add("tiers", tiers)
186 .toString();
187 }
188}