blob: d8edaffc5fa6bafdfffd475fe4620f000351d87c [file] [log] [blame]
Carmelo Cascone98dfdb72017-07-14 12:01:37 -04001/*
2 * Copyright 2017-present Open Networking Laboratory
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 */
16
17package org.onosproject.p4runtime.ctl;
18
19
20import com.google.common.collect.Maps;
21import com.google.protobuf.Message;
22import p4.config.P4InfoOuterClass.Action;
23import p4.config.P4InfoOuterClass.ActionProfile;
24import p4.config.P4InfoOuterClass.ControllerPacketMetadata;
25import p4.config.P4InfoOuterClass.Counter;
26import p4.config.P4InfoOuterClass.DirectCounter;
27import p4.config.P4InfoOuterClass.DirectMeter;
28import p4.config.P4InfoOuterClass.MatchField;
29import p4.config.P4InfoOuterClass.Meter;
30import p4.config.P4InfoOuterClass.P4Info;
31import p4.config.P4InfoOuterClass.Preamble;
32import p4.config.P4InfoOuterClass.Table;
33
34import java.util.Map;
35
36import static java.lang.String.format;
37
38/**
39 * Utility class to easily retrieve information from a P4Info protobuf message.
40 */
41final class P4InfoBrowser {
42
43 private final EntityBrowser<Table> tables = new EntityBrowser<>("table");
44 private final EntityBrowser<Action> actions = new EntityBrowser<>("action");
45 private final EntityBrowser<ActionProfile> actionProfiles = new EntityBrowser<>("action profile");
46 private final EntityBrowser<Counter> counters = new EntityBrowser<>("counter");
47 private final EntityBrowser<DirectCounter> directCounters = new EntityBrowser<>("direct counter");
48 private final EntityBrowser<Meter> meters = new EntityBrowser<>("meter");
49 private final EntityBrowser<DirectMeter> directMeters = new EntityBrowser<>("direct meter");
50 private final EntityBrowser<ControllerPacketMetadata> ctrlPktMetadatas =
51 new EntityBrowser<>("controller packet metadata");
52 private final Map<Integer, EntityBrowser<Action.Param>> actionParams = Maps.newHashMap();
53 private final Map<Integer, EntityBrowser<MatchField>> matchFields = Maps.newHashMap();
54
55 /**
56 * Creates a new browser for the given P4Info.
57 *
58 * @param p4info P4Info protobuf message
59 */
60 P4InfoBrowser(P4Info p4info) {
61 parseP4Info(p4info);
62 }
63
64 private void parseP4Info(P4Info p4info) {
65 p4info.getTablesList().forEach(
66 entity -> {
67 tables.addWithPreamble(entity.getPreamble(), entity);
68 // Index match fields.
69 int tableId = entity.getPreamble().getId();
70 String tableName = entity.getPreamble().getName();
71 EntityBrowser<MatchField> matchFieldBrowser = new EntityBrowser<>(format(
72 "match field for table '%s'", tableName));
73 entity.getMatchFieldsList().forEach(m -> matchFieldBrowser.add(m.getName(), m.getId(), m));
74 matchFields.put(tableId, matchFieldBrowser);
75 });
76
77 p4info.getActionsList().forEach(
78 entity -> {
79 actions.addWithPreamble(entity.getPreamble(), entity);
80 // Index action params.
81 int actionId = entity.getPreamble().getId();
82 String actionName = entity.getPreamble().getName();
83 EntityBrowser<Action.Param> paramBrowser = new EntityBrowser<>(format(
84 "param for action '%s'", actionName));
85 entity.getParamsList().forEach(p -> paramBrowser.add(p.getName(), p.getId(), p));
86 actionParams.put(actionId, paramBrowser);
87 });
88
89 p4info.getActionProfilesList().forEach(
90 entity -> actionProfiles.addWithPreamble(entity.getPreamble(), entity));
91
92 p4info.getCountersList().forEach(
93 entity -> counters.addWithPreamble(entity.getPreamble(), entity));
94
95 p4info.getDirectCountersList().forEach(
96 entity -> directCounters.addWithPreamble(entity.getPreamble(), entity));
97
98 p4info.getMetersList().forEach(
99 entity -> meters.addWithPreamble(entity.getPreamble(), entity));
100
101 p4info.getDirectMetersList().forEach(
102 entity -> directMeters.addWithPreamble(entity.getPreamble(), entity));
103
104 p4info.getControllerPacketMetadataList().forEach(
105 entity -> ctrlPktMetadatas.addWithPreamble(entity.getPreamble(), entity));
106 }
107
108 /**
109 * Returns a browser for tables.
110 *
111 * @return table browser
112 */
113 EntityBrowser<Table> tables() {
114 return tables;
115 }
116
117 /**
118 * Returns a browser for actions.
119 *
120 * @return action browser
121 */
122 EntityBrowser<Action> actions() {
123 return actions;
124 }
125
126 /**
127 * Returns a browser for action profiles.
128 *
129 * @return action profile browser
130 */
131 EntityBrowser<ActionProfile> actionProfiles() {
132 return actionProfiles;
133 }
134
135 /**
136 * Returns a browser for counters.
137 *
138 * @return counter browser
139 */
140 EntityBrowser<Counter> counters() {
141 return counters;
142 }
143
144 /**
145 * Returns a browser for direct counters.
146 *
147 * @return direct counter browser
148 */
149 EntityBrowser<DirectCounter> directCounters() {
150 return directCounters;
151 }
152
153 /**
154 * Returns a browser for meters.
155 *
156 * @return meter browser
157 */
158 EntityBrowser<Meter> meters() {
159 return meters;
160 }
161
162 /**
163 * Returns a browser for direct meters.
164 *
165 * @return table browser
166 */
167 EntityBrowser<DirectMeter> directMeters() {
168 return directMeters;
169 }
170
171 /**
172 * Returns a browser for controller packet metadata.
173 *
174 * @return controller packet metadata browser
175 */
176 EntityBrowser<ControllerPacketMetadata> controllerPacketMetadatas() {
177 return ctrlPktMetadatas;
178 }
179
180 /**
181 * Returns a browser for params of the given action.
182 *
183 * @param actionId action identifier
184 * @return action params browser
185 * @throws NotFoundException if the action cannot be found
186 */
187 EntityBrowser<Action.Param> actionParams(int actionId) throws NotFoundException {
188 // Throws exception if action id is not found.
189 actions.getById(actionId);
190 return actionParams.get(actionId);
191 }
192
193 /**
194 * Returns a browser for match fields of the given table.
195 *
196 * @param tableId table identifier
197 * @return controller packet metadata browser
198 * @throws NotFoundException if the table cannot be found
199 */
200 EntityBrowser<MatchField> matchFields(int tableId) throws NotFoundException {
201 // Throws exception if action id is not found.
202 tables.getById(tableId);
203 return matchFields.get(tableId);
204 }
205
206 /**
207 * Browser of P4Info entities.
208 *
209 * @param <T> protobuf message type
210 */
211 static final class EntityBrowser<T extends Message> {
212
213 private String entityName;
214 private final Map<String, T> names = Maps.newHashMap();
215 private final Map<String, T> aliases = Maps.newHashMap();
216 private final Map<Integer, T> ids = Maps.newHashMap();
217
218 private EntityBrowser(String entityName) {
219 this.entityName = entityName;
220 }
221
222 /**
223 * Adds the given entity identified by the given name and id.
224 *
225 * @param name entity name
226 * @param id entity id
227 * @param entity entity message
228 */
229 void add(String name, int id, T entity) {
230 names.put(name, entity);
231 ids.put(id, entity);
232 }
233
234 /**
235 * Adds the given entity identified by the given P4Info preamble.
236 *
237 * @param preamble P4Info preamble protobuf message
238 * @param entity entity message
239 */
240 void addWithPreamble(Preamble preamble, T entity) {
241 names.put(preamble.getName(), entity);
242 aliases.put(preamble.getName(), entity);
243 ids.put(preamble.getId(), entity);
244 }
245
246 /**
247 * Returns true if the P4Info defines an entity with such name, false otherwise.
248 *
249 * @param name entity name
250 * @return boolean
251 */
252 boolean hasName(String name) {
253 return names.containsKey(name);
254 }
255
256 /**
257 * Returns the entity identified by the given name, if present, otherwise, throws an exception.
258 *
259 * @param name entity name
260 * @return entity message
261 * @throws NotFoundException if the entity cannot be found
262 */
263 T getByName(String name) throws NotFoundException {
264 if (!hasName(name)) {
265 throw new NotFoundException(entityName, name);
266 }
267 return names.get(name);
268 }
269
270 /**
271 * Returns true if the P4Info defines an entity with such alias, false otherwise.
272 *
273 * @param alias entity alias
274 * @return boolean
275 */
276 boolean hasAlias(String alias) {
277 return aliases.containsKey(alias);
278 }
279
280 /**
281 * Returns the entity identified by the given alias, if present, otherwise, throws an exception.
282 *
283 * @param alias entity alias
284 * @return entity message
285 * @throws NotFoundException if the entity cannot be found
286 */
287 T getByAlias(String alias) throws NotFoundException {
288 if (!hasName(alias)) {
289 throw new NotFoundException(entityName, alias);
290 }
291 return aliases.get(alias);
292 }
293
294 /**
295 * Returns true if the P4Info defines an entity with such id, false otherwise.
296 *
297 * @param id entity id
298 * @return boolean
299 */
300 boolean hasId(int id) {
301 return ids.containsKey(id);
302 }
303
304 /**
305 * Returns the entity identified by the given id, if present, otherwise, throws an exception.
306 *
307 * @param id entity id
308 * @return entity message
309 * @throws NotFoundException if the entity cannot be found
310 */
311 T getById(int id) throws NotFoundException {
312 if (!hasId(id)) {
313 throw new NotFoundException(entityName, id);
314 }
315 return ids.get(id);
316 }
317 }
318
319 /**
320 * Signals tha an entity cannot be found in the P4Info.
321 */
322 public static class NotFoundException extends Exception {
323
324 NotFoundException(String entityName, String key) {
325 super(format("No such %s in P4Info with name/alias '%s'", entityName, key));
326 }
327
328 NotFoundException(String entityName, int id) {
329 super(format("No such %s in P4Info with id '%d'", entityName, id));
330 }
331 }
332}