blob: ee3c3c3e120cdc45160c4477f9932691a921a6e9 [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();
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700188 case ACTION:
189 default:
190 return tableAction.toString();
191 }
192 }
193
Carmelo Cascone7b821702017-06-19 11:26:08 +0900194 /**
195 * Returns a table entry builder.
196 *
197 * @return a new builder
198 */
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400199 public static Builder builder() {
200 return new Builder();
201 }
202
Carmelo Cascone1a7e4f92017-11-20 23:04:02 -0800203 @Override
204 public PiEntityType piEntityType() {
205 return PiEntityType.TABLE_ENTRY;
206 }
207
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800208 @Override
209 public PiTableEntryHandle handle(DeviceId deviceId) {
210 return PiTableEntryHandle.of(deviceId, this);
211 }
212
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400213 public static final class Builder {
214
215 private PiTableId tableId;
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700216 private PiMatchKey matchKey = PiMatchKey.EMPTY;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400217 private PiTableAction tableAction;
218 private long cookie = 0;
219 private int priority = NO_PRIORITY;
220 private double timeout = NO_TIMEOUT;
steven308017632e152018-10-20 00:51:08 +0800221 private PiCounterCellData counterData;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400222
223 private Builder() {
224 // Hides constructor.
225 }
226
227 /**
228 * Sets the table identifier for this entry.
229 *
230 * @param tableId table identifier
231 * @return this
232 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900233 public Builder forTable(PiTableId tableId) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700234 this.tableId = checkNotNull(tableId, "Table ID cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400235 return this;
236 }
237
238 /**
239 * Sets the action of this table entry.
240 *
241 * @param tableAction table action
242 * @return this
243 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900244 public Builder withAction(PiTableAction tableAction) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700245 this.tableAction = checkNotNull(tableAction, "Action cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400246 return this;
247 }
248
249 /**
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700250 * Sets the match key of this table entry. By default, the match key is
251 * {@link PiMatchKey#EMPTY}, i.e. any match.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400252 *
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200253 * @param matchKey match key
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400254 * @return this
255 */
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200256 public Builder withMatchKey(PiMatchKey matchKey) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700257 this.matchKey = checkNotNull(matchKey, "Match key cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400258 return this;
259 }
260
261 /**
262 * Sets the cookie, i.e. a controller-specific metadata.
263 *
264 * @param cookie cookie
265 * @return this
266 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900267 public Builder withCookie(long cookie) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400268 this.cookie = cookie;
269 return this;
270 }
271
272 /**
273 * Sets the priority of this table entry.
274 *
275 * @param priority priority
276 * @return this
277 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900278 public Builder withPriority(int priority) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400279 checkArgument(priority >= 0, "Priority must be a positive integer.");
280 this.priority = priority;
281 return this;
282 }
283
284 /**
285 * Sets the timeout of this table entry.
286 *
287 * @param seconds timeout in seconds
288 * @return this
289 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900290 public Builder withTimeout(double seconds) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400291 checkArgument(seconds > 0, "Timeout must be greater than zero.");
292 this.timeout = seconds;
293 return this;
294 }
295
296 /**
steven308017632e152018-10-20 00:51:08 +0800297 * Sets the counter cell data of this table entry.
298 *
299 * @param data counter cell data
300 * @return this
301 */
302 public Builder withCounterCellData(PiCounterCellData data) {
303 this.counterData = checkNotNull(data, "Counter cell data cannot be null");
304 return this;
305 }
306
307 /**
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400308 * Builds the table entry.
309 *
310 * @return a new table entry
311 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900312 public PiTableEntry build() {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400313 checkNotNull(tableId);
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700314 checkNotNull(matchKey);
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700315 final boolean isDefaultAction = matchKey.equals(PiMatchKey.EMPTY);
316 return new PiTableEntry(tableId, matchKey, tableAction,
steven308017632e152018-10-20 00:51:08 +0800317 isDefaultAction, cookie, priority, timeout, counterData);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400318 }
319 }
320}