blob: 9ecbeca89c380481b917453045d0f89da6cab700 [file] [log] [blame]
Yi Tsenga87b40c2017-09-10 00:59:03 -07001/*
2 * Copyright 2017-present Open Networking Foundation
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.ui.impl;
18
19import com.fasterxml.jackson.databind.node.ObjectNode;
20import com.google.common.collect.ImmutableSet;
21import com.google.common.collect.Sets;
22import org.onosproject.codec.CodecContext;
23import org.onosproject.net.Device;
24import org.onosproject.net.DeviceId;
25import org.onosproject.net.device.DeviceService;
26import org.onosproject.net.pi.model.PiActionModel;
27import org.onosproject.net.pi.model.PiHeaderFieldModel;
28import org.onosproject.net.pi.model.PiHeaderModel;
29import org.onosproject.net.pi.model.PiHeaderTypeModel;
30import org.onosproject.net.pi.model.PiPipeconf;
31import org.onosproject.net.pi.model.PiPipeconfId;
32import org.onosproject.net.pi.model.PiPipelineInterpreter;
33import org.onosproject.net.pi.model.PiPipelineModel;
34import org.onosproject.net.pi.model.PiTableMatchFieldModel;
35import org.onosproject.net.pi.model.PiTableModel;
36import org.onosproject.net.pi.runtime.PiPipeconfService;
37import org.onosproject.net.pi.runtime.PiTableId;
38import org.onosproject.ui.RequestHandler;
39import org.onosproject.ui.UiMessageHandler;
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43import java.util.Collection;
44import java.util.Optional;
45import java.util.Set;
46
47public class PipeconfViewMessageHandler extends UiMessageHandler {
48 private static final Logger log =
49 LoggerFactory.getLogger(PipeconfViewMessageHandler.class);
50 private static final String PIPECONF_REQUEST = "pipeconfRequest";
51 private static final String PIPECONF_RESP = "pipeConfResponse";
52 private static final String DEVICE_ID = "devId";
53 private static final String PIPECONF = "pipeconf";
54 private static final String PIPELINE_MODEL = "pipelineModel";
55 private static final String NO_PIPECONF_RESP = "noPipeconfResp";
56
57 @Override
58 protected Collection<RequestHandler> createRequestHandlers() {
59 return ImmutableSet.of(new PipeconfRequestHandler());
60 }
61
62 private class PipeconfRequestHandler extends RequestHandler {
63
64 public PipeconfRequestHandler() {
65 super(PIPECONF_REQUEST);
66 }
67
68 @Override
69 public void process(ObjectNode payload) {
70 PiPipeconfService piPipeconfService = get(PiPipeconfService.class);
71 DeviceService deviceService = get(DeviceService.class);
72 ObjectNode responseData = objectNode();
73 String devId = string(payload, DEVICE_ID);
74 if (devId == null || devId.isEmpty()) {
75 log.warn("{}: Invalid device id", PIPECONF_REQUEST);
76 sendMessage(NO_PIPECONF_RESP, null);
77 return;
78 }
79 DeviceId deviceId = DeviceId.deviceId(devId);
80 Optional<PiPipeconfId> pipeconfId = piPipeconfService.ofDevice(deviceId);
81 if (!pipeconfId.isPresent()) {
82 log.warn("{}: Can't find pipeconf id for device {}", PIPECONF_REQUEST, deviceId);
83 sendMessage(NO_PIPECONF_RESP, null);
84 return;
85 }
86
87 Optional<PiPipeconf> pipeconf = piPipeconfService.getPipeconf(pipeconfId.get());
88 if (!pipeconf.isPresent()) {
89 log.warn("{}: Can't find pipeconf {}", PIPECONF_REQUEST, pipeconfId);
90 sendMessage(NO_PIPECONF_RESP, null);
91 return;
92 }
93 CodecContext codecContext = getJsonCodecContext();
94
95 ObjectNode pipeconfData = codecContext.encode(pipeconf.get(), PiPipeconf.class);
96 responseData.set(PIPECONF, pipeconfData);
97
98 // Filtered out models not exists in interpreter
99 // usually they generated by compiler automatically
100 Device device = deviceService.getDevice(deviceId);
101 if (device == null || !deviceService.isAvailable(deviceId)) {
102 log.warn("{}: Device {} is not available", PIPECONF_REQUEST, deviceId);
103 sendMessage(NO_PIPECONF_RESP, null);
104 return;
105 }
106 PiPipelineInterpreter interpreter = device.as(PiPipelineInterpreter.class);
107 PiPipelineModel pipelineModel =
108 filteredOutAdditionalData(pipeconf.get().pipelineModel(), interpreter);
109
110 ObjectNode pipelineModelData =
111 codecContext.encode(pipelineModel, PiPipelineModel.class);
112 responseData.set(PIPELINE_MODEL, pipelineModelData);
113
114 sendMessage(PIPECONF_RESP, responseData);
115 }
116 }
117
118 private PiPipelineModel filteredOutAdditionalData(PiPipelineModel piPipelineModel,
119 PiPipelineInterpreter interpreter) {
120 if (interpreter == null) {
121 // Do nothing if there is no interpreter
122 return piPipelineModel;
123 }
124 // filter out actions, headers and tables if not exists in interpreter
125 Set<PiHeaderTypeModel> newHeaderTypesModels = Sets.newHashSet();
126 Set<PiHeaderModel> newHeaderModels = Sets.newHashSet();
127 Set<PiActionModel> newActionModels = Sets.newHashSet();
128 Set<PiTableModel> newTableModels = Sets.newHashSet();
129
130 piPipelineModel.tables().forEach(table -> {
131 String tableName = table.name();
132 PiTableId tableId = PiTableId.of(tableName);
133
134 if (interpreter.mapPiTableId(tableId).isPresent()) {
135 newTableModels.add(table);
136
137 newActionModels.addAll(table.actions());
138 table.matchFields().stream()
139 .map(PiTableMatchFieldModel::field)
140 .map(PiHeaderFieldModel::header)
141 .forEach(header -> {
142 newHeaderModels.add(header);
143 newHeaderTypesModels.add(header.type());
144 });
145
146 }
147 });
148
149 return new FilteredPipelineModel(newHeaderTypesModels,
150 newHeaderModels,
151 newActionModels,
152 newTableModels);
153 }
154
155 /**
156 * Pipeline model for UI message.
157 * FIXME: Is it necessary to create this class?
158 */
159 private class FilteredPipelineModel implements PiPipelineModel {
160
161 private Set<PiHeaderTypeModel> headerTypesModels;
162 private Set<PiHeaderModel> headerModels;
163 private Set<PiActionModel> actionModels;
164 private Set<PiTableModel> tableModels;
165
166 public FilteredPipelineModel(Set<PiHeaderTypeModel> headerTypesModels,
167 Set<PiHeaderModel> headerModels,
168 Set<PiActionModel> actionModels,
169 Set<PiTableModel> tableModels) {
170 this.headerTypesModels = headerTypesModels;
171 this.headerModels = headerModels;
172 this.actionModels = actionModels;
173 this.tableModels = tableModels;
174 }
175
176 @Override
177 public Optional<PiHeaderTypeModel> headerType(String name) {
178 return headerTypesModels.stream()
179 .filter(headerType -> headerType.name().equals(name))
180 .findFirst();
181 }
182
183 @Override
184 public Collection<PiHeaderTypeModel> headerTypes() {
185 return headerTypesModels;
186 }
187
188 @Override
189 public Optional<PiHeaderModel> header(String name) {
190 return headerModels.stream()
191 .filter(headerModel -> headerModel.name().equals(name))
192 .findFirst();
193 }
194
195 @Override
196 public Collection<PiHeaderModel> headers() {
197 return headerModels;
198 }
199
200 @Override
201 public Optional<PiActionModel> action(String name) {
202 return actionModels.stream()
203 .filter(actionModel -> actionModel.name().equals(name))
204 .findFirst();
205 }
206
207 @Override
208 public Collection<PiActionModel> actions() {
209 return actionModels;
210 }
211
212 @Override
213 public Optional<PiTableModel> table(String name) {
214 return tableModels.stream()
215 .filter(tableModel -> tableModel.name().equals(name))
216 .findFirst();
217 }
218
219 @Override
220 public Collection<PiTableModel> tables() {
221 return tableModels;
222 }
223 }
224}