blob: 15c1a0d8676c8f55367d65063cecd87eaea6c242 [file] [log] [blame]
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -04001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -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
Andrea Campanella0288c872017-08-07 18:32:51 +020017package org.onosproject.drivers.p4runtime;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040018
Carmelo Cascone58136812018-07-19 03:40:16 +020019import com.google.common.collect.ImmutableList;
Yi Tseng8d355132018-04-13 01:40:48 +080020import com.google.common.collect.Sets;
Carmelo Cascone58136812018-07-19 03:40:16 +020021import com.google.common.util.concurrent.Striped;
22import org.apache.commons.lang3.tuple.Pair;
Carmelo Casconee75b7942017-11-21 17:14:49 -080023import org.onosproject.drivers.p4runtime.mirror.P4RuntimeGroupMirror;
Carmelo Cascone58136812018-07-19 03:40:16 +020024import org.onosproject.drivers.p4runtime.mirror.P4RuntimeMulticastGroupMirror;
Yi Tseng76737cf2018-01-31 17:13:21 -080025import org.onosproject.drivers.p4runtime.mirror.TimedEntry;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040026import org.onosproject.net.DeviceId;
Carmelo Casconee75b7942017-11-21 17:14:49 -080027import org.onosproject.net.group.DefaultGroup;
Yi Tseng82512da2017-08-16 19:46:36 -070028import org.onosproject.net.group.Group;
Carmelo Cascone58136812018-07-19 03:40:16 +020029import org.onosproject.net.group.GroupDescription;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040030import org.onosproject.net.group.GroupOperation;
31import org.onosproject.net.group.GroupOperations;
32import org.onosproject.net.group.GroupProgrammable;
Yi Tseng82512da2017-08-16 19:46:36 -070033import org.onosproject.net.group.GroupStore;
Carmelo Cascone87892e22017-11-13 16:01:29 -080034import org.onosproject.net.pi.model.PiActionProfileId;
Carmelo Casconee75b7942017-11-21 17:14:49 -080035import org.onosproject.net.pi.model.PiActionProfileModel;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040036import org.onosproject.net.pi.runtime.PiActionGroup;
Carmelo Casconee75b7942017-11-21 17:14:49 -080037import org.onosproject.net.pi.runtime.PiActionGroupHandle;
Yi Tseng8d355132018-04-13 01:40:48 +080038import org.onosproject.net.pi.runtime.PiActionGroupMember;
Carmelo Cascone58136812018-07-19 03:40:16 +020039import org.onosproject.net.pi.runtime.PiMulticastGroupEntry;
40import org.onosproject.net.pi.runtime.PiMulticastGroupEntryHandle;
Carmelo Casconee75b7942017-11-21 17:14:49 -080041import org.onosproject.net.pi.service.PiGroupTranslator;
Carmelo Cascone58136812018-07-19 03:40:16 +020042import org.onosproject.net.pi.service.PiMulticastGroupTranslator;
Carmelo Casconee75b7942017-11-21 17:14:49 -080043import org.onosproject.net.pi.service.PiTranslatedEntity;
Carmelo Cascone326ad2d2017-11-28 18:09:13 -080044import org.onosproject.net.pi.service.PiTranslationException;
Carmelo Cascone58136812018-07-19 03:40:16 +020045import org.onosproject.p4runtime.api.P4RuntimeClient;
Yi Tseng82512da2017-08-16 19:46:36 -070046import org.slf4j.Logger;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040047
Yi Tseng82512da2017-08-16 19:46:36 -070048import java.util.Collection;
49import java.util.Collections;
Carmelo Casconee75b7942017-11-21 17:14:49 -080050import java.util.Objects;
Yi Tseng82512da2017-08-16 19:46:36 -070051import java.util.concurrent.CompletableFuture;
Yi Tseng82512da2017-08-16 19:46:36 -070052import java.util.concurrent.locks.Lock;
Carmelo Casconee75b7942017-11-21 17:14:49 -080053import java.util.stream.Collectors;
54import java.util.stream.Stream;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040055
Carmelo Casconee5b28722018-06-22 17:28:28 +020056import static java.lang.String.format;
Carmelo Casconee75b7942017-11-21 17:14:49 -080057import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.DELETE;
58import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.INSERT;
Yi Tseng8d355132018-04-13 01:40:48 +080059import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.MODIFY;
Yi Tseng82512da2017-08-16 19:46:36 -070060import static org.slf4j.LoggerFactory.getLogger;
61
62/**
63 * Implementation of the group programmable behaviour for P4Runtime.
Carmelo Cascone58136812018-07-19 03:40:16 +020064 * <p>
65 * This implementation distinguishes between ALL groups, and other types. ALL
66 * groups are handled via PRE multicast group programming, while other types are
67 * handled via action profile group programming.
Yi Tseng82512da2017-08-16 19:46:36 -070068 */
Carmelo Casconee75b7942017-11-21 17:14:49 -080069public class P4RuntimeGroupProgrammable
70 extends AbstractP4RuntimeHandlerBehaviour
71 implements GroupProgrammable {
72
Carmelo Casconee75b7942017-11-21 17:14:49 -080073 private static final String ACT_GRP_MEMS_STR = "action group members";
74 private static final String DELETE_STR = "delete";
75 private static final String ACT_GRP_STR = "action group";
76 private static final String INSERT_STR = "insert";
Yi Tseng8d355132018-04-13 01:40:48 +080077 private static final String MODIFY_STR = "modify";
Carmelo Casconee75b7942017-11-21 17:14:49 -080078
Yi Tseng82512da2017-08-16 19:46:36 -070079 private static final Logger log = getLogger(P4RuntimeGroupProgrammable.class);
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040080
Carmelo Casconee75b7942017-11-21 17:14:49 -080081 // If true, we ignore re-installing groups that are already known in the
82 // device mirror.
Yi Tsengf325a602018-06-27 18:26:33 +080083 private static final String CHECK_MIRROR_BEFORE_UPDATE = "checkMirrorBeforeUpdate";
84 private static final boolean DEFAULT_CHECK_MIRROR_BEFORE_UPDATE = true;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040085
Yi Tseng76737cf2018-01-31 17:13:21 -080086 // If true, we avoid querying the device and return what's already known by
87 // the ONOS store.
Yi Tsengf325a602018-06-27 18:26:33 +080088 private static final String IGNORE_DEVICE_WHEN_GET = "ignoreDeviceWhenGet";
89 private static final boolean DEFAULT_IGNORE_DEVICE_WHEN_GET = false;
Yi Tseng76737cf2018-01-31 17:13:21 -080090
Esin Karaman971fb7f2017-12-28 13:44:52 +000091 protected GroupStore groupStore;
Carmelo Casconee75b7942017-11-21 17:14:49 -080092 private P4RuntimeGroupMirror groupMirror;
Carmelo Cascone58136812018-07-19 03:40:16 +020093 private PiGroupTranslator groupTranslator;
94 private P4RuntimeMulticastGroupMirror mcGroupMirror;
95 private PiMulticastGroupTranslator mcGroupTranslator;
Yi Tseng82512da2017-08-16 19:46:36 -070096
97 // Needed to synchronize operations over the same group.
Carmelo Cascone58136812018-07-19 03:40:16 +020098 private static final Striped<Lock> STRIPED_LOCKS = Striped.lock(30);
Yi Tseng82512da2017-08-16 19:46:36 -070099
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400100 @Override
Carmelo Casconee75b7942017-11-21 17:14:49 -0800101 protected boolean setupBehaviour() {
102 if (!super.setupBehaviour()) {
103 return false;
104 }
105 groupMirror = this.handler().get(P4RuntimeGroupMirror.class);
Carmelo Cascone58136812018-07-19 03:40:16 +0200106 mcGroupMirror = this.handler().get(P4RuntimeMulticastGroupMirror.class);
Carmelo Casconee75b7942017-11-21 17:14:49 -0800107 groupStore = handler().get(GroupStore.class);
Carmelo Cascone58136812018-07-19 03:40:16 +0200108 groupTranslator = piTranslationService.groupTranslator();
109 mcGroupTranslator = piTranslationService.multicastGroupTranslator();
Carmelo Casconee75b7942017-11-21 17:14:49 -0800110 return true;
111 }
112
113 @Override
114 public void performGroupOperation(DeviceId deviceId,
115 GroupOperations groupOps) {
Carmelo Cascone87b9b392017-10-02 18:33:20 +0200116 if (!setupBehaviour()) {
Yi Tseng82512da2017-08-16 19:46:36 -0700117 return;
118 }
Carmelo Cascone58136812018-07-19 03:40:16 +0200119 groupOps.operations().stream()
120 // Get group type and operation type
121 .map(op -> Pair.of(groupStore.getGroup(deviceId, op.groupId()),
122 op.opType()))
123 .forEach(pair -> {
124 if (pair.getLeft().type().equals(GroupDescription.Type.ALL)) {
125 processMcGroupOp(deviceId, pair.getLeft(), pair.getRight());
126 } else {
127 processGroupOp(deviceId, pair.getLeft(), pair.getRight());
128 }
129 });
Yi Tseng82512da2017-08-16 19:46:36 -0700130 }
131
Yi Tseng82512da2017-08-16 19:46:36 -0700132 @Override
133 public Collection<Group> getGroups() {
Carmelo Cascone87b9b392017-10-02 18:33:20 +0200134 if (!setupBehaviour()) {
135 return Collections.emptyList();
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400136 }
Carmelo Cascone58136812018-07-19 03:40:16 +0200137 final ImmutableList.Builder<Group> groups = ImmutableList.builder();
138
Yi Tsengf325a602018-06-27 18:26:33 +0800139 if (!driverBoolProperty(IGNORE_DEVICE_WHEN_GET, DEFAULT_IGNORE_DEVICE_WHEN_GET)) {
Carmelo Cascone58136812018-07-19 03:40:16 +0200140 groups.addAll(pipeconf.pipelineModel().actionProfiles().stream()
141 .map(PiActionProfileModel::id)
142 .flatMap(this::streamGroupsFromDevice)
143 .iterator());
144 // FIXME: enable reading MC groups from device once reading from
145 // PRE is supported in PI
146 // groups.addAll(getMcGroupsFromDevice());
Yi Tseng76737cf2018-01-31 17:13:21 -0800147 } else {
Carmelo Cascone58136812018-07-19 03:40:16 +0200148 groups.addAll(groupMirror.getAll(deviceId).stream()
149 .map(TimedEntry::entry)
150 .map(this::forgeGroupEntry)
151 .iterator());
Yi Tseng76737cf2018-01-31 17:13:21 -0800152 }
Carmelo Cascone58136812018-07-19 03:40:16 +0200153 // FIXME: same as before..
154 groups.addAll(mcGroupMirror.getAll(deviceId).stream()
155 .map(TimedEntry::entry)
156 .map(this::forgeMcGroupEntry)
157 .iterator());
158
159 return groups.build();
Carmelo Casconee75b7942017-11-21 17:14:49 -0800160 }
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400161
Carmelo Cascone58136812018-07-19 03:40:16 +0200162 private void processGroupOp(DeviceId deviceId, Group pdGroup, GroupOperation.Type opType) {
Carmelo Casconee75b7942017-11-21 17:14:49 -0800163 final PiActionGroup piGroup;
164 try {
Carmelo Cascone58136812018-07-19 03:40:16 +0200165 piGroup = groupTranslator.translate(pdGroup, pipeconf);
Carmelo Casconee75b7942017-11-21 17:14:49 -0800166 } catch (PiTranslationException e) {
Carmelo Cascone58136812018-07-19 03:40:16 +0200167 log.warn("Unable to translate group, aborting {} operation: {} [{}]",
168 opType, e.getMessage(), pdGroup);
Carmelo Casconee75b7942017-11-21 17:14:49 -0800169 return;
170 }
Carmelo Casconee75b7942017-11-21 17:14:49 -0800171 final PiActionGroupHandle handle = PiActionGroupHandle.of(deviceId, piGroup);
172
173 final PiActionGroup groupOnDevice = groupMirror.get(handle) == null
174 ? null
175 : groupMirror.get(handle).entry();
176
Carmelo Cascone58136812018-07-19 03:40:16 +0200177 final Lock lock = STRIPED_LOCKS.get(handle);
Carmelo Casconee75b7942017-11-21 17:14:49 -0800178 lock.lock();
179 try {
Carmelo Casconee75b7942017-11-21 17:14:49 -0800180 processPiGroup(handle, piGroup,
Carmelo Cascone58136812018-07-19 03:40:16 +0200181 groupOnDevice, pdGroup, opType);
182 } finally {
183 lock.unlock();
184 }
185 }
186
187 private void processMcGroupOp(DeviceId deviceId, Group pdGroup, GroupOperation.Type opType) {
188 final PiMulticastGroupEntry mcGroup;
189 try {
190 mcGroup = mcGroupTranslator.translate(pdGroup, pipeconf);
191 } catch (PiTranslationException e) {
192 log.warn("Unable to translate multicast group, aborting {} operation: {} [{}]",
193 opType, e.getMessage(), pdGroup);
194 return;
195 }
196 final PiMulticastGroupEntryHandle handle = PiMulticastGroupEntryHandle.of(
197 deviceId, mcGroup);
198 final PiMulticastGroupEntry groupOnDevice = mcGroupMirror.get(handle) == null
199 ? null
200 : mcGroupMirror.get(handle).entry();
201 final Lock lock = STRIPED_LOCKS.get(handle);
202 lock.lock();
203 try {
204 processMcGroup(handle, mcGroup,
205 groupOnDevice, pdGroup, opType);
Carmelo Casconee75b7942017-11-21 17:14:49 -0800206 } finally {
207 lock.unlock();
Yi Tseng82512da2017-08-16 19:46:36 -0700208 }
209 }
210
Carmelo Casconee75b7942017-11-21 17:14:49 -0800211 private void processPiGroup(PiActionGroupHandle handle,
212 PiActionGroup groupToApply,
213 PiActionGroup groupOnDevice,
Yi Tseng8d355132018-04-13 01:40:48 +0800214 Group pdGroup, GroupOperation.Type operationType) {
215 if (operationType == GroupOperation.Type.ADD) {
Carmelo Casconee75b7942017-11-21 17:14:49 -0800216 if (groupOnDevice != null) {
Yi Tseng8d355132018-04-13 01:40:48 +0800217 log.warn("Unable to add group {} since group already on device {}",
218 groupToApply.id(), deviceId);
219 log.debug("To apply: {}", groupToApply);
220 log.debug("On device: {}", groupOnDevice);
221 return;
Carmelo Casconee75b7942017-11-21 17:14:49 -0800222 }
Yi Tseng8d355132018-04-13 01:40:48 +0800223
Carmelo Casconee75b7942017-11-21 17:14:49 -0800224 if (writeGroupToDevice(groupToApply)) {
225 groupMirror.put(handle, groupToApply);
Carmelo Cascone58136812018-07-19 03:40:16 +0200226 groupTranslator.learn(handle, new PiTranslatedEntity<>(
Carmelo Casconee75b7942017-11-21 17:14:49 -0800227 pdGroup, groupToApply, handle));
228 }
Yi Tseng8d355132018-04-13 01:40:48 +0800229 } else if (operationType == GroupOperation.Type.MODIFY) {
230 if (groupOnDevice == null) {
231 log.warn("Group {} does not exists on device {}, can not modify it",
232 groupToApply.id(), deviceId);
233 return;
234 }
Yi Tsengf325a602018-06-27 18:26:33 +0800235 if (driverBoolProperty(CHECK_MIRROR_BEFORE_UPDATE, DEFAULT_CHECK_MIRROR_BEFORE_UPDATE)
Yi Tseng8d355132018-04-13 01:40:48 +0800236 && groupOnDevice.equals(groupToApply)) {
237 // Group on device has the same members, ignore operation.
238 return;
239 }
240 if (modifyGroupFromDevice(groupToApply, groupOnDevice)) {
241 groupMirror.put(handle, groupToApply);
Carmelo Cascone58136812018-07-19 03:40:16 +0200242 groupTranslator.learn(handle,
243 new PiTranslatedEntity<>(pdGroup, groupToApply, handle));
Yi Tseng8d355132018-04-13 01:40:48 +0800244 }
Carmelo Casconee75b7942017-11-21 17:14:49 -0800245 } else {
Yi Tseng8d355132018-04-13 01:40:48 +0800246 if (groupOnDevice == null) {
247 log.warn("Unable to remove group {} from device {} since it does" +
248 "not exists on device.", groupToApply.id(), deviceId);
249 return;
250 }
251 if (deleteGroupFromDevice(groupOnDevice)) {
Carmelo Casconee75b7942017-11-21 17:14:49 -0800252 groupMirror.remove(handle);
Carmelo Cascone58136812018-07-19 03:40:16 +0200253 groupTranslator.forget(handle);
Carmelo Casconee75b7942017-11-21 17:14:49 -0800254 }
255 }
256 }
257
Carmelo Cascone58136812018-07-19 03:40:16 +0200258 private void processMcGroup(PiMulticastGroupEntryHandle handle,
259 PiMulticastGroupEntry groupToApply,
260 PiMulticastGroupEntry groupOnDevice,
261 Group pdGroup, GroupOperation.Type opType) {
262 if (opType == GroupOperation.Type.DELETE) {
263 if (writeMcGroupOnDevice(groupToApply, DELETE)) {
264 mcGroupMirror.remove(handle);
265 mcGroupTranslator.forget(handle);
266 }
267 return;
268 }
269
270 final P4RuntimeClient.WriteOperationType p4OpType =
271 opType == GroupOperation.Type.ADD ? INSERT : MODIFY;
272
273 if (driverBoolProperty(CHECK_MIRROR_BEFORE_UPDATE,
274 DEFAULT_CHECK_MIRROR_BEFORE_UPDATE)
275 && p4OpType == MODIFY
276 && groupOnDevice != null
277 && groupOnDevice.equals(groupToApply)) {
278 // Ignore.
279 return;
280 }
281
282 if (writeMcGroupOnDevice(groupToApply, p4OpType)) {
283 mcGroupMirror.put(handle, groupToApply);
284 mcGroupTranslator.learn(handle, new PiTranslatedEntity<>(
285 pdGroup, groupToApply, handle));
286 }
287 }
288
289 private boolean writeMcGroupOnDevice(PiMulticastGroupEntry group, P4RuntimeClient.WriteOperationType opType) {
290 return getFutureWithDeadline(
291 client.writePreMulticastGroupEntries(
292 Collections.singleton(group), opType),
293 "performing multicast group " + opType, false);
294 }
295
Yi Tseng8d355132018-04-13 01:40:48 +0800296 private boolean modifyGroupFromDevice(PiActionGroup groupToApply, PiActionGroup groupOnDevice) {
297 PiActionProfileId groupProfileId = groupToApply.actionProfileId();
298 Collection<PiActionGroupMember> membersToRemove = Sets.newHashSet(groupOnDevice.members());
299 membersToRemove.removeAll(groupToApply.members());
300 Collection<PiActionGroupMember> membersToAdd = Sets.newHashSet(groupToApply.members());
301 membersToAdd.removeAll(groupOnDevice.members());
302
303 if (!membersToAdd.isEmpty() &&
304 !completeFuture(client.writeActionGroupMembers(groupProfileId, membersToAdd, INSERT, pipeconf),
305 ACT_GRP_MEMS_STR, INSERT_STR)) {
306 // remove what we added
307 completeFuture(client.writeActionGroupMembers(groupProfileId, membersToAdd, DELETE, pipeconf),
308 ACT_GRP_MEMS_STR, INSERT_STR);
309 return false;
310 }
311
312 if (!completeFuture(client.writeActionGroup(groupToApply, MODIFY, pipeconf),
313 ACT_GRP_STR, MODIFY_STR)) {
314 // recover group information
315 completeFuture(client.writeActionGroup(groupOnDevice, MODIFY, pipeconf),
316 ACT_GRP_STR, MODIFY_STR);
317 // remove what we added
318 completeFuture(client.writeActionGroupMembers(groupProfileId, membersToAdd, DELETE, pipeconf),
319 ACT_GRP_MEMS_STR, INSERT_STR);
320 return false;
321 }
322
323 if (!membersToRemove.isEmpty() &&
324 !completeFuture(client.writeActionGroupMembers(groupProfileId, membersToRemove, DELETE, pipeconf),
Carmelo Casconee5b28722018-06-22 17:28:28 +0200325 ACT_GRP_MEMS_STR, DELETE_STR)) {
Yi Tseng8d355132018-04-13 01:40:48 +0800326 // add what we removed
327 completeFuture(client.writeActionGroupMembers(groupProfileId, membersToRemove, INSERT, pipeconf),
328 ACT_GRP_MEMS_STR, DELETE_STR);
329 // recover group information
330 completeFuture(client.writeActionGroup(groupOnDevice, MODIFY, pipeconf),
331 ACT_GRP_STR, MODIFY_STR);
332 // remove what we added
333 completeFuture(client.writeActionGroupMembers(groupProfileId, membersToAdd, DELETE, pipeconf),
334 ACT_GRP_MEMS_STR, INSERT_STR);
335 return false;
336 }
337
338 return true;
339 }
340
Carmelo Casconee75b7942017-11-21 17:14:49 -0800341 private boolean writeGroupToDevice(PiActionGroup groupToApply) {
342 // First insert members, then group.
343 // The operation is deemed successful if both operations are successful.
344 // FIXME: add transactional semantics, i.e. remove members if group fails.
345 final boolean membersSuccess = completeFuture(
Yi Tseng8d355132018-04-13 01:40:48 +0800346 client.writeActionGroupMembers(groupToApply.actionProfileId(),
347 groupToApply.members(),
348 INSERT, pipeconf),
Carmelo Casconee75b7942017-11-21 17:14:49 -0800349 ACT_GRP_MEMS_STR, INSERT_STR);
350 return membersSuccess && completeFuture(
351 client.writeActionGroup(groupToApply, INSERT, pipeconf),
352 ACT_GRP_STR, INSERT_STR);
353 }
354
355 private boolean deleteGroupFromDevice(PiActionGroup piActionGroup) {
356 // First delete group, then members.
357 // The operation is deemed successful if both operations are successful.
358 final boolean groupSuccess = completeFuture(
359 client.writeActionGroup(piActionGroup, DELETE, pipeconf),
360 ACT_GRP_STR, DELETE_STR);
361 return groupSuccess && completeFuture(
Yi Tseng8d355132018-04-13 01:40:48 +0800362 client.writeActionGroupMembers(piActionGroup.actionProfileId(),
363 piActionGroup.members(),
364 DELETE, pipeconf),
Carmelo Casconee75b7942017-11-21 17:14:49 -0800365 ACT_GRP_MEMS_STR, DELETE_STR);
366 }
367
368 private boolean completeFuture(CompletableFuture<Boolean> completableFuture,
369 String topic, String action) {
Carmelo Casconee5b28722018-06-22 17:28:28 +0200370 return getFutureWithDeadline(
371 completableFuture, format("performing %s %s", action, topic), false);
Carmelo Casconee75b7942017-11-21 17:14:49 -0800372 }
373
374 private Stream<Group> streamGroupsFromDevice(PiActionProfileId actProfId) {
Carmelo Casconee5b28722018-06-22 17:28:28 +0200375 // Read PI groups and return original PD one.
376 Collection<PiActionGroup> groups = getFutureWithDeadline(
377 client.dumpGroups(actProfId, pipeconf),
378 "dumping groups", Collections.emptyList());
379 return groups.stream()
380 .map(this::forgeGroupEntry)
381 .filter(Objects::nonNull);
Carmelo Casconee75b7942017-11-21 17:14:49 -0800382 }
383
Carmelo Cascone58136812018-07-19 03:40:16 +0200384 private Collection<Group> getMcGroupsFromDevice() {
385 Collection<PiMulticastGroupEntry> groups = getFutureWithDeadline(
386 client.readAllMulticastGroupEntries(),
387 "dumping multicast groups", Collections.emptyList());
388 return groups.stream()
389 .map(this::forgeMcGroupEntry)
390 .filter(Objects::nonNull)
391 .collect(Collectors.toList());
392 }
393
Carmelo Casconee75b7942017-11-21 17:14:49 -0800394 private Group forgeGroupEntry(PiActionGroup piGroup) {
395 final PiActionGroupHandle handle = PiActionGroupHandle.of(deviceId, piGroup);
Carmelo Cascone58136812018-07-19 03:40:16 +0200396 if (!groupTranslator.lookup(handle).isPresent()) {
Carmelo Casconee75b7942017-11-21 17:14:49 -0800397 log.warn("Missing PI group from translation store: {} - {}:{}",
398 pipeconf.id(), piGroup.actionProfileId(),
399 piGroup.id());
400 return null;
401 }
402 final long life = groupMirror.get(handle) != null
403 ? groupMirror.get(handle).lifeSec() : 0;
Carmelo Cascone58136812018-07-19 03:40:16 +0200404 final Group original = groupTranslator.lookup(handle).get().original();
405 return addedGroup(original, life);
406 }
407
408 private Group forgeMcGroupEntry(PiMulticastGroupEntry mcGroup) {
409 final PiMulticastGroupEntryHandle handle = PiMulticastGroupEntryHandle.of(
410 deviceId, mcGroup);
411 if (!mcGroupTranslator.lookup(handle).isPresent()) {
412 log.warn("Missing PI multicast group {} from translation store",
413 mcGroup.groupId());
414 return null;
415 }
416 final long life = mcGroupMirror.get(handle) != null
417 ? mcGroupMirror.get(handle).lifeSec() : 0;
418 final Group original = mcGroupTranslator.lookup(handle).get().original();
419 return addedGroup(original, life);
420 }
421
422 private Group addedGroup(Group original, long life) {
Carmelo Casconee75b7942017-11-21 17:14:49 -0800423 final DefaultGroup forgedGroup = new DefaultGroup(original.id(), original);
424 forgedGroup.setState(Group.GroupState.ADDED);
425 forgedGroup.setLife(life);
426 return forgedGroup;
427 }
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400428}