blob: ac73bbef2289e382d84769b92d2d9511bb35e4dd [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;
steven308017632e152018-10-20 00:51:08 +080045 private final PiCounterCellData counterData;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040046
Carmelo Cascone0e896a02017-07-31 07:22:27 +020047 private PiTableEntry(PiTableId tableId, PiMatchKey matchKey,
Carmelo Cascone50d195f2018-09-11 13:26:38 -070048 PiTableAction tableAction, boolean isDefaultAction,
steven308017632e152018-10-20 00:51:08 +080049 long cookie, int priority, double timeout, PiCounterCellData data) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040050 this.tableId = tableId;
Carmelo Cascone0e896a02017-07-31 07:22:27 +020051 this.matchKey = matchKey;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040052 this.tableAction = tableAction;
Carmelo Cascone50d195f2018-09-11 13:26:38 -070053 this.isDefaultAction = isDefaultAction;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040054 this.cookie = cookie;
55 this.priority = priority;
56 this.timeout = timeout;
steven308017632e152018-10-20 00:51:08 +080057 this.counterData = data;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040058 }
59
60 /**
61 * Returns the table where this entry is installed.
62 *
63 * @return table identifier
64 */
65 public PiTableId table() {
66 return tableId;
67 }
68
69 /**
Carmelo Cascone0e896a02017-07-31 07:22:27 +020070 * Returns the match key of this table entry.
Carmelo Cascone50d195f2018-09-11 13:26:38 -070071 * <p>
72 * If {@link #isDefaultAction()} is {@code true} this method returns the
73 * empty match key ({@link PiMatchKey#EMPTY}).
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040074 *
Carmelo Cascone0e896a02017-07-31 07:22:27 +020075 * @return match key
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040076 */
Carmelo Cascone0e896a02017-07-31 07:22:27 +020077 public PiMatchKey matchKey() {
78 return matchKey;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040079 }
80
81 /**
82 * Returns the action of this table entry.
83 *
84 * @return action
85 */
86 public PiTableAction action() {
87 return tableAction;
88 }
89
90 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -070091 * Returns true if this table entry contains the default action for this
92 * table, a.k.a. table-miss entry, false otherwise.
93 *
94 * @return boolean
95 */
96 public boolean isDefaultAction() {
97 return isDefaultAction;
98 }
99
100 /**
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400101 * Returns the cookie of this table entry.
102 *
103 * @return cookie
104 */
105 public long cookie() {
106 return cookie;
107 }
108
109 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700110 * Returns the priority of this table entry, if present. If the priority
111 * value is not present, then this table entry has no explicit priority.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400112 *
113 * @return optional priority
114 */
115 public Optional<Integer> priority() {
116 return priority == NO_PRIORITY ? Optional.empty() : Optional.of(priority);
117 }
118
119 /**
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700120 * Returns the timeout in seconds of this table entry, if present. If the
121 * timeout value is not present, then this table entry is meant to be
122 * permanent.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400123 *
124 * @return optional timeout value in seconds
125 */
126 public Optional<Double> timeout() {
127 return timeout == NO_TIMEOUT ? Optional.empty() : Optional.of(timeout);
128 }
129
steven308017632e152018-10-20 00:51:08 +0800130 /**
131 * Returns the data of the counter cell associated with this table entry.
132 * This method is meaningful only if the table entry was read from the
133 * infrastructure device and the table has direct counters, otherwise
134 * returns null.
135 *
136 * @return counter cell data
137 */
138 public PiCounterCellData counter() {
139 return counterData;
140 }
141
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400142 @Override
143 public boolean equals(Object o) {
144 if (this == o) {
145 return true;
146 }
147 if (o == null || getClass() != o.getClass()) {
148 return false;
149 }
150 PiTableEntry that = (PiTableEntry) o;
151 return priority == that.priority &&
Carmelo Casconee44592f2018-09-12 02:24:47 -0700152 cookie == that.cookie &&
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400153 Double.compare(that.timeout, timeout) == 0 &&
154 Objects.equal(tableId, that.tableId) &&
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200155 Objects.equal(matchKey, that.matchKey) &&
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700156 Objects.equal(isDefaultAction, that.isDefaultAction) &&
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400157 Objects.equal(tableAction, that.tableAction);
158 }
159
160 @Override
161 public int hashCode() {
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700162 return Objects.hashCode(tableId, matchKey, isDefaultAction, tableAction,
Carmelo Casconee44592f2018-09-12 02:24:47 -0700163 priority, cookie, timeout);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400164 }
165
166 @Override
167 public String toString() {
168 return MoreObjects.toStringHelper(this)
169 .add("tableId", tableId)
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700170 .add("matchKey", isDefaultAction ? "DEFAULT-ACTION" : matchKey)
171 .add("tableAction", tableActionToString(tableAction))
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400172 .add("priority", priority == NO_PRIORITY ? "N/A" : String.valueOf(priority))
173 .add("timeout", timeout == NO_TIMEOUT ? "PERMANENT" : String.valueOf(timeout))
174 .toString();
175 }
176
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700177 private String tableActionToString(PiTableAction tableAction) {
178 if (tableAction == null) {
179 return "null";
180 }
181 switch (tableAction.type()) {
182 case ACTION_GROUP_ID:
183 return "GROUP:" + ((PiActionGroupId) tableAction).id();
184 case GROUP_MEMBER_ID:
185 return "GROUP_MEMBER:" + ((PiActionGroupMemberId) tableAction).id();
186 case ACTION:
187 default:
188 return tableAction.toString();
189 }
190 }
191
Carmelo Cascone7b821702017-06-19 11:26:08 +0900192 /**
193 * Returns a table entry builder.
194 *
195 * @return a new builder
196 */
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400197 public static Builder builder() {
198 return new Builder();
199 }
200
Carmelo Cascone1a7e4f92017-11-20 23:04:02 -0800201 @Override
202 public PiEntityType piEntityType() {
203 return PiEntityType.TABLE_ENTRY;
204 }
205
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400206 public static final class Builder {
207
208 private PiTableId tableId;
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700209 private PiMatchKey matchKey = PiMatchKey.EMPTY;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400210 private PiTableAction tableAction;
211 private long cookie = 0;
212 private int priority = NO_PRIORITY;
213 private double timeout = NO_TIMEOUT;
steven308017632e152018-10-20 00:51:08 +0800214 private PiCounterCellData counterData;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400215
216 private Builder() {
217 // Hides constructor.
218 }
219
220 /**
221 * Sets the table identifier for this entry.
222 *
223 * @param tableId table identifier
224 * @return this
225 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900226 public Builder forTable(PiTableId tableId) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700227 this.tableId = checkNotNull(tableId, "Table ID cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400228 return this;
229 }
230
231 /**
232 * Sets the action of this table entry.
233 *
234 * @param tableAction table action
235 * @return this
236 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900237 public Builder withAction(PiTableAction tableAction) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700238 this.tableAction = checkNotNull(tableAction, "Action cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400239 return this;
240 }
241
242 /**
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700243 * Sets the match key of this table entry. By default, the match key is
244 * {@link PiMatchKey#EMPTY}, i.e. any match.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400245 *
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200246 * @param matchKey match key
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400247 * @return this
248 */
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200249 public Builder withMatchKey(PiMatchKey matchKey) {
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700250 this.matchKey = checkNotNull(matchKey, "Match key cannot be null");
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400251 return this;
252 }
253
254 /**
255 * Sets the cookie, i.e. a controller-specific metadata.
256 *
257 * @param cookie cookie
258 * @return this
259 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900260 public Builder withCookie(long cookie) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400261 this.cookie = cookie;
262 return this;
263 }
264
265 /**
266 * Sets the priority of this table entry.
267 *
268 * @param priority priority
269 * @return this
270 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900271 public Builder withPriority(int priority) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400272 checkArgument(priority >= 0, "Priority must be a positive integer.");
273 this.priority = priority;
274 return this;
275 }
276
277 /**
278 * Sets the timeout of this table entry.
279 *
280 * @param seconds timeout in seconds
281 * @return this
282 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900283 public Builder withTimeout(double seconds) {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400284 checkArgument(seconds > 0, "Timeout must be greater than zero.");
285 this.timeout = seconds;
286 return this;
287 }
288
289 /**
steven308017632e152018-10-20 00:51:08 +0800290 * Sets the counter cell data of this table entry.
291 *
292 * @param data counter cell data
293 * @return this
294 */
295 public Builder withCounterCellData(PiCounterCellData data) {
296 this.counterData = checkNotNull(data, "Counter cell data cannot be null");
297 return this;
298 }
299
300 /**
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400301 * Builds the table entry.
302 *
303 * @return a new table entry
304 */
Carmelo Cascone00a59962017-06-16 17:51:49 +0900305 public PiTableEntry build() {
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400306 checkNotNull(tableId);
Carmelo Casconef03f6e92018-04-04 11:39:39 -0700307 checkNotNull(matchKey);
Carmelo Cascone50d195f2018-09-11 13:26:38 -0700308 final boolean isDefaultAction = matchKey.equals(PiMatchKey.EMPTY);
309 return new PiTableEntry(tableId, matchKey, tableAction,
steven308017632e152018-10-20 00:51:08 +0800310 isDefaultAction, cookie, priority, timeout, counterData);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -0400311 }
312 }
313}