blob: 40ad4de15a2fec61f39efe053967ca97cf36b0da [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 Cascone4c289b72019-01-22 15:30:45 -080022import org.onosproject.net.DeviceId;
Carmelo Cascone87892e22017-11-13 16:01:29 -080023import org.onosproject.net.pi.model.PiTableId;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040024
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040025import java.util.Optional;
Carmelo Cascone4c289b72019-01-22 15:30:45 -080026import java.util.OptionalInt;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040027
28import static com.google.common.base.Preconditions.checkArgument;
29import static com.google.common.base.Preconditions.checkNotNull;
30
31/**
Carmelo Cascone87892e22017-11-13 16:01:29 -080032 * Instance of a table entry in a protocol-independent pipeline.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040033 */
34@Beta
Carmelo Cascone1a7e4f92017-11-20 23:04:02 -080035public final class PiTableEntry implements PiEntity {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040036
37 private static final int NO_PRIORITY = -1;
38 private static final double NO_TIMEOUT = -1;
39
40 private final PiTableId tableId;
Carmelo Cascone0e896a02017-07-31 07:22:27 +020041 private final PiMatchKey matchKey;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040042 private final PiTableAction tableAction;
Carmelo Cascone50d195f2018-09-11 13:26:38 -070043 private final boolean isDefaultAction;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040044 private final long cookie;
45 private final int priority;
46 private final double timeout;
steven308017632e152018-10-20 00:51:08 +080047 private final PiCounterCellData counterData;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040048
Carmelo Cascone0e896a02017-07-31 07:22:27 +020049 private PiTableEntry(PiTableId tableId, PiMatchKey matchKey,
Carmelo Cascone50d195f2018-09-11 13:26:38 -070050 PiTableAction tableAction, boolean isDefaultAction,
steven308017632e152018-10-20 00:51:08 +080051 long cookie, int priority, double timeout, PiCounterCellData data) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040052 this.tableId = tableId;
Carmelo Cascone0e896a02017-07-31 07:22:27 +020053 this.matchKey = matchKey;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040054 this.tableAction = tableAction;
Carmelo Cascone50d195f2018-09-11 13:26:38 -070055 this.isDefaultAction = isDefaultAction;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040056 this.cookie = cookie;
57 this.priority = priority;
58 this.timeout = timeout;
steven308017632e152018-10-20 00:51:08 +080059 this.counterData = data;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040060 }
61
62 /**
63 * Returns the table where this entry is installed.
64 *
65 * @return table identifier
66 */
67 public PiTableId table() {
68 return tableId;
69 }
70
71 /**
Carmelo Cascone0e896a02017-07-31 07:22:27 +020072 * Returns the match key of this table entry.
Carmelo Cascone50d195f2018-09-11 13:26:38 -070073 * <p>
74 * If {@link #isDefaultAction()} is {@code true} this method returns the
75 * empty match key ({@link PiMatchKey#EMPTY}).
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040076 *
Carmelo Cascone0e896a02017-07-31 07:22:27 +020077 * @return match key
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040078 */
Carmelo Cascone0e896a02017-07-31 07:22:27 +020079 public PiMatchKey matchKey() {
80 return matchKey;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040081 }
82
83 /**
84 * Returns the action of this table entry.
85 *
86 * @return action
87 */
88 public PiTableAction action() {
89 return tableAction;
90 }
91
92 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -070093 * Returns true if this table entry contains the default action for this
94 * table, a.k.a. table-miss entry, false otherwise.
95 *
96 * @return boolean
97 */
98 public boolean isDefaultAction() {
99 return isDefaultAction;
100 }
101
102 /**
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400103 * Returns the cookie of this table entry.
104 *
105 * @return cookie
106 */
107 public long cookie() {
108 return cookie;
109 }
110
111 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700112 * Returns the priority of this table entry, if present. If the priority
113 * value is not present, then this table entry has no explicit priority.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400114 *
115 * @return optional priority
116 */
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800117 public OptionalInt priority() {
118 return priority == NO_PRIORITY ? OptionalInt.empty() : OptionalInt.of(priority);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400119 }
120
121 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700122 * Returns the timeout in seconds of this table entry, if present. If the
123 * timeout value is not present, then this table entry is meant to be
124 * permanent.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400125 *
126 * @return optional timeout value in seconds
127 */
128 public Optional<Double> timeout() {
129 return timeout == NO_TIMEOUT ? Optional.empty() : Optional.of(timeout);
130 }
131
steven308017632e152018-10-20 00:51:08 +0800132 /**
133 * Returns the data of the counter cell associated with this table entry.
134 * This method is meaningful only if the table entry was read from the
135 * infrastructure device and the table has direct counters, otherwise
136 * returns null.
137 *
138 * @return counter cell data
139 */
140 public PiCounterCellData counter() {
141 return counterData;
142 }
143
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400144 @Override
145 public boolean equals(Object o) {
146 if (this == o) {
147 return true;
148 }
149 if (o == null || getClass() != o.getClass()) {
150 return false;
151 }
152 PiTableEntry that = (PiTableEntry) o;
153 return priority == that.priority &&
Carmelo Casconee44592f2018-09-12 02:24:47 -0700154 cookie == that.cookie &&
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400155 Double.compare(that.timeout, timeout) == 0 &&
156 Objects.equal(tableId, that.tableId) &&
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200157 Objects.equal(matchKey, that.matchKey) &&
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700158 Objects.equal(isDefaultAction, that.isDefaultAction) &&
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400159 Objects.equal(tableAction, that.tableAction);
160 }
161
162 @Override
163 public int hashCode() {
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700164 return Objects.hashCode(tableId, matchKey, isDefaultAction, tableAction,
Carmelo Casconee44592f2018-09-12 02:24:47 -0700165 priority, cookie, timeout);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400166 }
167
168 @Override
169 public String toString() {
170 return MoreObjects.toStringHelper(this)
171 .add("tableId", tableId)
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700172 .add("matchKey", isDefaultAction ? "DEFAULT-ACTION" : matchKey)
173 .add("tableAction", tableActionToString(tableAction))
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400174 .add("priority", priority == NO_PRIORITY ? "N/A" : String.valueOf(priority))
175 .add("timeout", timeout == NO_TIMEOUT ? "PERMANENT" : String.valueOf(timeout))
176 .toString();
177 }
178
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700179 private String tableActionToString(PiTableAction tableAction) {
180 if (tableAction == null) {
181 return "null";
182 }
183 switch (tableAction.type()) {
Carmelo Casconecb4327a2018-09-11 15:17:23 -0700184 case ACTION_PROFILE_GROUP_ID:
185 return "ACT_PROF_GROUP:" + ((PiActionProfileGroupId) tableAction).id();
186 case ACTION_PROFILE_MEMBER_ID:
187 return "ACT_PROF_MEMBER:" + ((PiActionProfileMemberId) tableAction).id();
Daniele Morod900fe42021-02-11 16:12:57 +0100188 case ACTION_SET:
189 return "ACTION_SET:" + tableAction.toString();
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700190 case ACTION:
191 default:
192 return tableAction.toString();
193 }
194 }
195
Carmelo Cascone7b821702017-06-19 11:26:08 +0900196 /**
197 * Returns a table entry builder.
198 *
199 * @return a new builder
200 */
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400201 public static Builder builder() {
202 return new Builder();
203 }
204
Carmelo Cascone1a7e4f92017-11-20 23:04:02 -0800205 @Override
206 public PiEntityType piEntityType() {
207 return PiEntityType.TABLE_ENTRY;
208 }
209
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800210 @Override
211 public PiTableEntryHandle handle(DeviceId deviceId) {
212 return PiTableEntryHandle.of(deviceId, this);
213 }
214
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400215 public static final class Builder {
216
217 private PiTableId tableId;
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700218 private PiMatchKey matchKey = PiMatchKey.EMPTY;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400219 private PiTableAction tableAction;
220 private long cookie = 0;
221 private int priority = NO_PRIORITY;
222 private double timeout = NO_TIMEOUT;
steven308017632e152018-10-20 00:51:08 +0800223 private PiCounterCellData counterData;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400224
225 private Builder() {
226 // Hides constructor.
227 }
228
229 /**
230 * Sets the table identifier for this entry.
231 *
232 * @param tableId table identifier
233 * @return this
234 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900235 public Builder forTable(PiTableId tableId) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700236 this.tableId = checkNotNull(tableId, "Table ID cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400237 return this;
238 }
239
240 /**
241 * Sets the action of this table entry.
242 *
243 * @param tableAction table action
244 * @return this
245 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900246 public Builder withAction(PiTableAction tableAction) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700247 this.tableAction = checkNotNull(tableAction, "Action cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400248 return this;
249 }
250
251 /**
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700252 * Sets the match key of this table entry. By default, the match key is
253 * {@link PiMatchKey#EMPTY}, i.e. any match.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400254 *
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200255 * @param matchKey match key
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400256 * @return this
257 */
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200258 public Builder withMatchKey(PiMatchKey matchKey) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700259 this.matchKey = checkNotNull(matchKey, "Match key cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400260 return this;
261 }
262
263 /**
264 * Sets the cookie, i.e. a controller-specific metadata.
265 *
266 * @param cookie cookie
267 * @return this
268 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900269 public Builder withCookie(long cookie) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400270 this.cookie = cookie;
271 return this;
272 }
273
274 /**
275 * Sets the priority of this table entry.
276 *
277 * @param priority priority
278 * @return this
279 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900280 public Builder withPriority(int priority) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400281 checkArgument(priority >= 0, "Priority must be a positive integer.");
282 this.priority = priority;
283 return this;
284 }
285
286 /**
287 * Sets the timeout of this table entry.
288 *
289 * @param seconds timeout in seconds
290 * @return this
291 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900292 public Builder withTimeout(double seconds) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400293 checkArgument(seconds > 0, "Timeout must be greater than zero.");
294 this.timeout = seconds;
295 return this;
296 }
297
298 /**
steven308017632e152018-10-20 00:51:08 +0800299 * Sets the counter cell data of this table entry.
300 *
301 * @param data counter cell data
302 * @return this
303 */
304 public Builder withCounterCellData(PiCounterCellData data) {
305 this.counterData = checkNotNull(data, "Counter cell data cannot be null");
306 return this;
307 }
308
309 /**
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400310 * Builds the table entry.
311 *
312 * @return a new table entry
313 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900314 public PiTableEntry build() {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400315 checkNotNull(tableId);
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700316 checkNotNull(matchKey);
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700317 final boolean isDefaultAction = matchKey.equals(PiMatchKey.EMPTY);
318 return new PiTableEntry(tableId, matchKey, tableAction,
steven308017632e152018-10-20 00:51:08 +0800319 isDefaultAction, cookie, priority, timeout, counterData);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400320 }
321 }
322}