2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.impl.util;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Function;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.Iterables;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.Iterator;
19 import java.util.List;
20 import javax.annotation.Nullable;
21 import org.apache.commons.lang3.tuple.Pair;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.AddGroupsBatchOutput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.AddGroupsBatchOutputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.BatchGroupOutputListGrouping;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.RemoveGroupsBatchOutput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.RemoveGroupsBatchOutputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.UpdateGroupsBatchOutput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.UpdateGroupsBatchOutputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.batch.group.output.list.grouping.BatchFailedGroupsOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.batch.group.output.list.grouping.BatchFailedGroupsOutputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
40 import org.opendaylight.yangtools.yang.common.RpcError;
41 import org.opendaylight.yangtools.yang.common.RpcResult;
42 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
45 * Provides group util methods.
47 public final class GroupUtil {
49 private static final RpcResultBuilder<List<BatchFailedGroupsOutput>> SUCCESSFUL_GROUP_OUTPUT_RPC_RESULT =
50 RpcResultBuilder.success(Collections.<BatchFailedGroupsOutput>emptyList());
52 public static final Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<AddGroupsBatchOutput>>
54 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<AddGroupsBatchOutput>>() {
57 public RpcResult<AddGroupsBatchOutput> apply(
58 @Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
59 final AddGroupsBatchOutput batchOutput = new AddGroupsBatchOutputBuilder()
60 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
62 final RpcResultBuilder<AddGroupsBatchOutput> resultBld =
63 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
64 return resultBld.build();
67 public static final Function<Pair<RpcResult<AddGroupsBatchOutput>,
69 RpcResult<AddGroupsBatchOutput>>
70 GROUP_ADD_COMPOSING_TRANSFORM = createComposingFunction();
72 public static final Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<RemoveGroupsBatchOutput>>
73 GROUP_REMOVE_TRANSFORM =
74 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<RemoveGroupsBatchOutput>>() {
77 public RpcResult<RemoveGroupsBatchOutput> apply(
78 @Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
79 final RemoveGroupsBatchOutput batchOutput = new RemoveGroupsBatchOutputBuilder()
80 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
82 final RpcResultBuilder<RemoveGroupsBatchOutput> resultBld =
83 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
84 return resultBld.build();
87 public static final Function<Pair<RpcResult<RemoveGroupsBatchOutput>,
89 RpcResult<RemoveGroupsBatchOutput>>
90 GROUP_REMOVE_COMPOSING_TRANSFORM = createComposingFunction();
92 public static final Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<UpdateGroupsBatchOutput>>
93 GROUP_UPDATE_TRANSFORM =
94 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<UpdateGroupsBatchOutput>>() {
97 public RpcResult<UpdateGroupsBatchOutput> apply(
98 @Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
99 final UpdateGroupsBatchOutput batchOutput = new UpdateGroupsBatchOutputBuilder()
100 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
102 final RpcResultBuilder<UpdateGroupsBatchOutput> resultBld =
103 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
104 return resultBld.build();
107 public static final Function<Pair<RpcResult<UpdateGroupsBatchOutput>,
109 RpcResult<UpdateGroupsBatchOutput>>
110 GROUP_UPDATE_COMPOSING_TRANSFORM = createComposingFunction();
112 private GroupUtil() {
113 throw new IllegalStateException("This class should not be instantiated.");
117 * Method build the group path.
118 * @param nodePath - node path
119 * @param groupId - group Id
120 * @return instance identifier assembled for given node and group
122 public static GroupRef buildGroupPath(final InstanceIdentifier<Node> nodePath, final GroupId groupId) {
123 final KeyedInstanceIdentifier<Group, GroupKey> groupPath = nodePath
124 .augmentation(FlowCapableNode.class)
125 .child(Group.class, new GroupKey(groupId));
127 return new GroupRef(groupPath);
130 public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>> createCumulatingFunction(
131 final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group>
133 return createCumulatingFunction(inputBatchGroups, Iterables.size(inputBatchGroups));
136 public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>> createCumulatingFunction(
137 final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group>
138 inputBatchGroups, final int sizeOfInputBatch) {
139 return new CumulatingFunction<O>(inputBatchGroups, sizeOfInputBatch).invoke();
143 * Method returns the bitmap of actions supported by each group.
145 * @param actionsSupported - list of supported actions
148 public static List<Long> extractGroupActionsSupportBitmap(final List<ActionType> actionsSupported) {
149 List<Long> supportActionByGroups = new ArrayList<>();
150 for (org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType supportedActions
151 : actionsSupported) {
152 long supportActionBitmap = 0;
153 supportActionBitmap |= supportedActions.isOFPATOUTPUT() ? 1 : 0;
154 supportActionBitmap |= supportedActions.isOFPATCOPYTTLOUT() ? 1 << 11 : 0;
155 supportActionBitmap |= supportedActions.isOFPATCOPYTTLIN() ? 1 << 12 : 0;
156 supportActionBitmap |= supportedActions.isOFPATSETMPLSTTL() ? 1 << 15 : 0;
157 supportActionBitmap |= supportedActions.isOFPATDECMPLSTTL() ? 1 << 16 : 0;
158 supportActionBitmap |= supportedActions.isOFPATPUSHVLAN() ? 1 << 17 : 0;
159 supportActionBitmap |= supportedActions.isOFPATPOPVLAN() ? 1 << 18 : 0;
160 supportActionBitmap |= supportedActions.isOFPATPUSHMPLS() ? 1 << 19 : 0;
161 supportActionBitmap |= supportedActions.isOFPATPOPMPLS() ? 1 << 20 : 0;
162 supportActionBitmap |= supportedActions.isOFPATSETQUEUE() ? 1 << 21 : 0;
163 supportActionBitmap |= supportedActions.isOFPATGROUP() ? 1 << 22 : 0;
164 supportActionBitmap |= supportedActions.isOFPATSETNWTTL() ? 1 << 23 : 0;
165 supportActionBitmap |= supportedActions.isOFPATDECNWTTL() ? 1 << 24 : 0;
166 supportActionBitmap |= supportedActions.isOFPATSETFIELD() ? 1 << 25 : 0;
167 supportActionBitmap |= supportedActions.isOFPATPUSHPBB() ? 1 << 26 : 0;
168 supportActionBitmap |= supportedActions.isOFPATPOPPBB() ? 1 << 27 : 0;
169 supportActionByGroups.add(supportActionBitmap);
171 return supportActionByGroups;
175 * Factory method: create {@link Function} which attaches barrier response to given {@link RpcResult}<T>
176 * and changes success flag if needed.
178 * Original rpcResult is the {@link Pair#getLeft()} and barrier result is the {@link Pair#getRight()}.
180 * @param <T> type of rpcResult value
181 * @return reusable static function
184 static <T extends BatchGroupOutputListGrouping> Function<Pair<RpcResult<T>, RpcResult<Void>>, RpcResult<T>>
185 createComposingFunction() {
186 return new Function<Pair<RpcResult<T>, RpcResult<Void>>, RpcResult<T>>() {
189 public RpcResult<T> apply(@Nullable final Pair<RpcResult<T>, RpcResult<Void>> input) {
190 final RpcResultBuilder<T> resultBld;
191 if (input.getLeft().isSuccessful() && input.getRight().isSuccessful()) {
192 resultBld = RpcResultBuilder.success();
194 resultBld = RpcResultBuilder.failed();
197 final ArrayList<RpcError> rpcErrors = new ArrayList<>(input.getLeft().getErrors());
198 rpcErrors.addAll(input.getRight().getErrors());
199 resultBld.withRpcErrors(rpcErrors);
201 resultBld.withResult(input.getLeft().getResult());
203 return resultBld.build();
209 * Wrap given list of problematic group-ids into {@link RpcResult} of given type.
211 * @param batchGroupsCumulativeResult list of ids failed groups
212 * @param batchOutput group operation type
213 * @return batch group operation output of given type containing list of group-ids and corresponding success flag
215 private static <T extends BatchGroupOutputListGrouping> RpcResultBuilder<T> createCumulativeRpcResult(
216 final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulativeResult, final T batchOutput) {
217 final RpcResultBuilder<T> resultBld;
218 if (batchGroupsCumulativeResult.isSuccessful()) {
219 resultBld = RpcResultBuilder.success(batchOutput);
221 resultBld = RpcResultBuilder.failed();
222 resultBld.withResult(batchOutput)
223 .withRpcErrors(batchGroupsCumulativeResult.getErrors());
228 private static class CumulatingFunction<O> {
229 private final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group>
231 private final int sizeOfInputBatch;
234 Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group>
235 inputBatchGroups, int sizeOfInputBatch) {
236 this.inputBatchGroups = inputBatchGroups;
237 this.sizeOfInputBatch = sizeOfInputBatch;
240 public Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>> invoke() {
241 return new Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>>() {
244 public RpcResult<List<BatchFailedGroupsOutput>> apply(@Nullable final List<RpcResult<O>> innerInput) {
245 final int sizeOfFutures = innerInput.size();
246 Preconditions.checkArgument(sizeOfFutures == sizeOfInputBatch,
247 "wrong amount of returned futures: {} <> {}", sizeOfFutures, sizeOfInputBatch);
249 final List<BatchFailedGroupsOutput> batchGroups = new ArrayList<>();
250 final Iterator<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group>
251 batchGroupIterator = inputBatchGroups.iterator();
253 Collection<RpcError> groupErrors = new ArrayList<>(sizeOfFutures);
256 for (RpcResult<O> groupModOutput : innerInput) {
257 final GroupId groupId = batchGroupIterator.next().getGroupId();
259 if (!groupModOutput.isSuccessful()) {
260 batchGroups.add(new BatchFailedGroupsOutputBuilder()
262 .setBatchOrder(batchOrder)
264 groupErrors.addAll(groupModOutput.getErrors());
269 final RpcResultBuilder<List<BatchFailedGroupsOutput>> resultBuilder;
270 if (!groupErrors.isEmpty()) {
271 resultBuilder = RpcResultBuilder.<List<BatchFailedGroupsOutput>>failed()
272 .withRpcErrors(groupErrors).withResult(batchGroups);
274 resultBuilder = SUCCESSFUL_GROUP_OUTPUT_RPC_RESULT;
276 return resultBuilder.build();