blob: f8a14601c0e88306683408abaac274537f842ace [file] [log] [blame]
Carmelo Cascone1022a4e2017-05-25 00:16:18 -04001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Carmelo Cascone1022a4e2017-05-25 00:16:18 -04003 *
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.pi.runtime;
18
19import com.google.common.annotations.Beta;
20import com.google.common.base.MoreObjects;
21import com.google.common.base.Objects;
Carmelo Cascone87892e22017-11-13 16:01:29 -080022import org.onosproject.net.pi.model.PiTableId;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040023
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040024import java.util.Optional;
25
26import static com.google.common.base.Preconditions.checkArgument;
27import static com.google.common.base.Preconditions.checkNotNull;
28
29/**
Carmelo Cascone87892e22017-11-13 16:01:29 -080030 * Instance of a table entry in a protocol-independent pipeline.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040031 */
32@Beta
Carmelo Cascone1a7e4f92017-11-20 23:04:02 -080033public final class PiTableEntry implements PiEntity {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040034
35 private static final int NO_PRIORITY = -1;
36 private static final double NO_TIMEOUT = -1;
37
38 private final PiTableId tableId;
Carmelo Cascone0e896a02017-07-31 07:22:27 +020039 private final PiMatchKey matchKey;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040040 private final PiTableAction tableAction;
Carmelo Cascone50d195f2018-09-11 13:26:38 -070041 private final boolean isDefaultAction;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040042 private final long cookie;
43 private final int priority;
44 private final double timeout;
45
Carmelo Cascone0e896a02017-07-31 07:22:27 +020046 private PiTableEntry(PiTableId tableId, PiMatchKey matchKey,
Carmelo Cascone50d195f2018-09-11 13:26:38 -070047 PiTableAction tableAction, boolean isDefaultAction,
48 long cookie, int priority, double timeout) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040049 this.tableId = tableId;
Carmelo Cascone0e896a02017-07-31 07:22:27 +020050 this.matchKey = matchKey;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040051 this.tableAction = tableAction;
Carmelo Cascone50d195f2018-09-11 13:26:38 -070052 this.isDefaultAction = isDefaultAction;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040053 this.cookie = cookie;
54 this.priority = priority;
55 this.timeout = timeout;
56 }
57
58 /**
59 * Returns the table where this entry is installed.
60 *
61 * @return table identifier
62 */
63 public PiTableId table() {
64 return tableId;
65 }
66
67 /**
Carmelo Cascone0e896a02017-07-31 07:22:27 +020068 * Returns the match key of this table entry.
Carmelo Cascone50d195f2018-09-11 13:26:38 -070069 * <p>
70 * If {@link #isDefaultAction()} is {@code true} this method returns the
71 * empty match key ({@link PiMatchKey#EMPTY}).
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040072 *
Carmelo Cascone0e896a02017-07-31 07:22:27 +020073 * @return match key
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040074 */
Carmelo Cascone0e896a02017-07-31 07:22:27 +020075 public PiMatchKey matchKey() {
76 return matchKey;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040077 }
78
79 /**
80 * Returns the action of this table entry.
81 *
82 * @return action
83 */
84 public PiTableAction action() {
85 return tableAction;
86 }
87
88 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -070089 * Returns true if this table entry contains the default action for this
90 * table, a.k.a. table-miss entry, false otherwise.
91 *
92 * @return boolean
93 */
94 public boolean isDefaultAction() {
95 return isDefaultAction;
96 }
97
98 /**
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040099 * Returns the cookie of this table entry.
100 *
101 * @return cookie
102 */
103 public long cookie() {
104 return cookie;
105 }
106
107 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700108 * Returns the priority of this table entry, if present. If the priority
109 * value is not present, then this table entry has no explicit priority.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400110 *
111 * @return optional priority
112 */
113 public Optional<Integer> priority() {
114 return priority == NO_PRIORITY ? Optional.empty() : Optional.of(priority);
115 }
116
117 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700118 * Returns the timeout in seconds of this table entry, if present. If the
119 * timeout value is not present, then this table entry is meant to be
120 * permanent.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400121 *
122 * @return optional timeout value in seconds
123 */
124 public Optional<Double> timeout() {
125 return timeout == NO_TIMEOUT ? Optional.empty() : Optional.of(timeout);
126 }
127
128 @Override
129 public boolean equals(Object o) {
130 if (this == o) {
131 return true;
132 }
133 if (o == null || getClass() != o.getClass()) {
134 return false;
135 }
136 PiTableEntry that = (PiTableEntry) o;
137 return priority == that.priority &&
Carmelo Casconee44592f2018-09-12 02:24:47 -0700138 cookie == that.cookie &&
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400139 Double.compare(that.timeout, timeout) == 0 &&
140 Objects.equal(tableId, that.tableId) &&
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200141 Objects.equal(matchKey, that.matchKey) &&
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700142 Objects.equal(isDefaultAction, that.isDefaultAction) &&
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400143 Objects.equal(tableAction, that.tableAction);
144 }
145
146 @Override
147 public int hashCode() {
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700148 return Objects.hashCode(tableId, matchKey, isDefaultAction, tableAction,
Carmelo Casconee44592f2018-09-12 02:24:47 -0700149 priority, cookie, timeout);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400150 }
151
152 @Override
153 public String toString() {
154 return MoreObjects.toStringHelper(this)
155 .add("tableId", tableId)
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700156 .add("matchKey", isDefaultAction ? "DEFAULT-ACTION" : matchKey)
157 .add("tableAction", tableActionToString(tableAction))
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400158 .add("priority", priority == NO_PRIORITY ? "N/A" : String.valueOf(priority))
159 .add("timeout", timeout == NO_TIMEOUT ? "PERMANENT" : String.valueOf(timeout))
160 .toString();
161 }
162
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700163 private String tableActionToString(PiTableAction tableAction) {
164 if (tableAction == null) {
165 return "null";
166 }
167 switch (tableAction.type()) {
168 case ACTION_GROUP_ID:
169 return "GROUP:" + ((PiActionGroupId) tableAction).id();
170 case GROUP_MEMBER_ID:
171 return "GROUP_MEMBER:" + ((PiActionGroupMemberId) tableAction).id();
172 case ACTION:
173 default:
174 return tableAction.toString();
175 }
176 }
177
Carmelo Cascone7b821702017-06-19 11:26:08 +0900178 /**
179 * Returns a table entry builder.
180 *
181 * @return a new builder
182 */
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400183 public static Builder builder() {
184 return new Builder();
185 }
186
Carmelo Cascone1a7e4f92017-11-20 23:04:02 -0800187 @Override
188 public PiEntityType piEntityType() {
189 return PiEntityType.TABLE_ENTRY;
190 }
191
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400192 public static final class Builder {
193
194 private PiTableId tableId;
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700195 private PiMatchKey matchKey = PiMatchKey.EMPTY;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400196 private PiTableAction tableAction;
197 private long cookie = 0;
198 private int priority = NO_PRIORITY;
199 private double timeout = NO_TIMEOUT;
200
201 private Builder() {
202 // Hides constructor.
203 }
204
205 /**
206 * Sets the table identifier for this entry.
207 *
208 * @param tableId table identifier
209 * @return this
210 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900211 public Builder forTable(PiTableId tableId) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700212 this.tableId = checkNotNull(tableId, "Table ID cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400213 return this;
214 }
215
216 /**
217 * Sets the action of this table entry.
218 *
219 * @param tableAction table action
220 * @return this
221 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900222 public Builder withAction(PiTableAction tableAction) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700223 this.tableAction = checkNotNull(tableAction, "Action cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400224 return this;
225 }
226
227 /**
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700228 * Sets the match key of this table entry. By default, the match key is
229 * {@link PiMatchKey#EMPTY}, i.e. any match.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400230 *
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200231 * @param matchKey match key
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400232 * @return this
233 */
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200234 public Builder withMatchKey(PiMatchKey matchKey) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700235 this.matchKey = checkNotNull(matchKey, "Match key cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400236 return this;
237 }
238
239 /**
240 * Sets the cookie, i.e. a controller-specific metadata.
241 *
242 * @param cookie cookie
243 * @return this
244 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900245 public Builder withCookie(long cookie) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400246 this.cookie = cookie;
247 return this;
248 }
249
250 /**
251 * Sets the priority of this table entry.
252 *
253 * @param priority priority
254 * @return this
255 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900256 public Builder withPriority(int priority) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400257 checkArgument(priority >= 0, "Priority must be a positive integer.");
258 this.priority = priority;
259 return this;
260 }
261
262 /**
263 * Sets the timeout of this table entry.
264 *
265 * @param seconds timeout in seconds
266 * @return this
267 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900268 public Builder withTimeout(double seconds) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400269 checkArgument(seconds > 0, "Timeout must be greater than zero.");
270 this.timeout = seconds;
271 return this;
272 }
273
274 /**
275 * Builds the table entry.
276 *
277 * @return a new table entry
278 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900279 public PiTableEntry build() {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400280 checkNotNull(tableId);
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700281 checkNotNull(matchKey);
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700282 final boolean isDefaultAction = matchKey.equals(PiMatchKey.EMPTY);
283 return new PiTableEntry(tableId, matchKey, tableAction,
284 isDefaultAction, cookie, priority, timeout);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400285 }
286 }
287}