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.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.common.RpcError;
40 import org.opendaylight.yangtools.yang.common.RpcResult;
41 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType;
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>> GROUP_ADD_TRANSFORM =
53 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<AddGroupsBatchOutput>>() {
56 public RpcResult<AddGroupsBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
57 final AddGroupsBatchOutput batchOutput = new AddGroupsBatchOutputBuilder()
58 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
60 final RpcResultBuilder<AddGroupsBatchOutput> resultBld =
61 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
62 return resultBld.build();
65 public static final Function<Pair<RpcResult<AddGroupsBatchOutput>, RpcResult<Void>>, RpcResult<AddGroupsBatchOutput>>
66 GROUP_ADD_COMPOSING_TRANSFORM = createComposingFunction();
68 public static final Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<RemoveGroupsBatchOutput>> GROUP_REMOVE_TRANSFORM =
69 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<RemoveGroupsBatchOutput>>() {
72 public RpcResult<RemoveGroupsBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
73 final RemoveGroupsBatchOutput batchOutput = new RemoveGroupsBatchOutputBuilder()
74 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
76 final RpcResultBuilder<RemoveGroupsBatchOutput> resultBld =
77 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
78 return resultBld.build();
81 public static final Function<Pair<RpcResult<RemoveGroupsBatchOutput>, RpcResult<Void>>, RpcResult<RemoveGroupsBatchOutput>>
82 GROUP_REMOVE_COMPOSING_TRANSFORM = createComposingFunction();
84 public static final Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<UpdateGroupsBatchOutput>> GROUP_UPDATE_TRANSFORM =
85 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<UpdateGroupsBatchOutput>>() {
88 public RpcResult<UpdateGroupsBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
89 final UpdateGroupsBatchOutput batchOutput = new UpdateGroupsBatchOutputBuilder()
90 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
92 final RpcResultBuilder<UpdateGroupsBatchOutput> resultBld =
93 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
94 return resultBld.build();
97 public static final Function<Pair<RpcResult<UpdateGroupsBatchOutput>, RpcResult<Void>>, RpcResult<UpdateGroupsBatchOutput>>
98 GROUP_UPDATE_COMPOSING_TRANSFORM = createComposingFunction();
100 private GroupUtil() {
101 throw new IllegalStateException("This class should not be instantiated.");
107 * @return instance identifier assembled for given node and group
109 public static GroupRef buildGroupPath(final InstanceIdentifier<Node> nodePath, final GroupId groupId) {
110 final KeyedInstanceIdentifier<Group, GroupKey> groupPath = nodePath
111 .augmentation(FlowCapableNode.class)
112 .child(Group.class, new GroupKey(groupId));
114 return new GroupRef(groupPath);
117 public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>> createCumulatingFunction(
118 final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group> inputBatchGroups) {
119 return createCumulatingFunction(inputBatchGroups, Iterables.size(inputBatchGroups));
122 public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>> createCumulatingFunction(
123 final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group> inputBatchGroups,
124 final int sizeOfInputBatch) {
125 return new CumulatingFunction<O>(inputBatchGroups, sizeOfInputBatch).invoke();
129 * Method returns the bitmap of actions supported by each group.
131 * @param actionsSupported
134 public static List<Long> extractGroupActionsSupportBitmap(final List<ActionType> actionsSupported) {
135 List<Long> supportActionByGroups = new ArrayList<>();
136 for (org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType supportedActions : actionsSupported) {
137 long supportActionBitmap = 0;
138 supportActionBitmap |= supportedActions.isOFPATOUTPUT() ? (1) : 0;
139 supportActionBitmap |= supportedActions.isOFPATCOPYTTLOUT() ? (1 << 11) : 0;
140 supportActionBitmap |= supportedActions.isOFPATCOPYTTLIN() ? (1 << 12) : 0;
141 supportActionBitmap |= supportedActions.isOFPATSETMPLSTTL() ? (1 << 15) : 0;
142 supportActionBitmap |= supportedActions.isOFPATDECMPLSTTL() ? (1 << 16) : 0;
143 supportActionBitmap |= supportedActions.isOFPATPUSHVLAN() ? (1 << 17) : 0;
144 supportActionBitmap |= supportedActions.isOFPATPOPVLAN() ? (1 << 18) : 0;
145 supportActionBitmap |= supportedActions.isOFPATPUSHMPLS() ? (1 << 19) : 0;
146 supportActionBitmap |= supportedActions.isOFPATPOPMPLS() ? (1 << 20) : 0;
147 supportActionBitmap |= supportedActions.isOFPATSETQUEUE() ? (1 << 21) : 0;
148 supportActionBitmap |= supportedActions.isOFPATGROUP() ? (1 << 22) : 0;
149 supportActionBitmap |= supportedActions.isOFPATSETNWTTL() ? (1 << 23) : 0;
150 supportActionBitmap |= supportedActions.isOFPATDECNWTTL() ? (1 << 24) : 0;
151 supportActionBitmap |= supportedActions.isOFPATSETFIELD() ? (1 << 25) : 0;
152 supportActionBitmap |= supportedActions.isOFPATPUSHPBB() ? (1 << 26) : 0;
153 supportActionBitmap |= supportedActions.isOFPATPOPPBB() ? (1 << 27) : 0;
154 supportActionByGroups.add(supportActionBitmap);
156 return supportActionByGroups;
160 * Factory method: create {@link Function} which attaches barrier response to given {@link RpcResult}<T>
161 * and changes success flag if needed.
163 * Original rpcResult is the {@link Pair#getLeft()} and barrier result is the {@link Pair#getRight()}.
165 * @param <T> type of rpcResult value
166 * @return reusable static function
169 static <T extends BatchGroupOutputListGrouping>
170 Function<Pair<RpcResult<T>, RpcResult<Void>>, RpcResult<T>> createComposingFunction() {
171 return new Function<Pair<RpcResult<T>, RpcResult<Void>>, RpcResult<T>>() {
174 public RpcResult<T> apply(@Nullable final Pair<RpcResult<T>, RpcResult<Void>> input) {
175 final RpcResultBuilder<T> resultBld;
176 if (input.getLeft().isSuccessful() && input.getRight().isSuccessful()) {
177 resultBld = RpcResultBuilder.success();
179 resultBld = RpcResultBuilder.failed();
182 final ArrayList<RpcError> rpcErrors = new ArrayList<>(input.getLeft().getErrors());
183 rpcErrors.addAll(input.getRight().getErrors());
184 resultBld.withRpcErrors(rpcErrors);
186 resultBld.withResult(input.getLeft().getResult());
188 return resultBld.build();
194 * Wrap given list of problematic group-ids into {@link RpcResult} of given type.
196 * @param batchGroupsCumulativeResult list of ids failed groups
198 * @param <T> group operation type
199 * @return batch group operation output of given type containing list of group-ids and corresponding success flag
201 private static <T extends BatchGroupOutputListGrouping>
202 RpcResultBuilder<T> createCumulativeRpcResult(@Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulativeResult,
203 final T batchOutput) {
204 final RpcResultBuilder<T> resultBld;
205 if (batchGroupsCumulativeResult.isSuccessful()) {
206 resultBld = RpcResultBuilder.success(batchOutput);
208 resultBld = RpcResultBuilder.failed();
209 resultBld.withResult(batchOutput)
210 .withRpcErrors(batchGroupsCumulativeResult.getErrors());
215 private static class CumulatingFunction<O> {
216 private final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group> inputBatchGroups;
217 private final int sizeOfInputBatch;
219 public CumulatingFunction(Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group> inputBatchGroups, int sizeOfInputBatch) {
220 this.inputBatchGroups = inputBatchGroups;
221 this.sizeOfInputBatch = sizeOfInputBatch;
224 public Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>> invoke() {
225 return new Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>>() {
228 public RpcResult<List<BatchFailedGroupsOutput>> apply(@Nullable final List<RpcResult<O>> innerInput) {
229 final int sizeOfFutures = innerInput.size();
230 Preconditions.checkArgument(sizeOfFutures == sizeOfInputBatch,
231 "wrong amount of returned futures: {} <> {}", sizeOfFutures, sizeOfInputBatch);
233 final List<BatchFailedGroupsOutput> batchGroups = new ArrayList<>();
234 final Iterator<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group>
235 batchGroupIterator = inputBatchGroups.iterator();
237 Collection<RpcError> groupErrors = new ArrayList<>(sizeOfFutures);
240 for (RpcResult<O> groupModOutput : innerInput) {
241 final GroupId groupId = batchGroupIterator.next().getGroupId();
243 if (!groupModOutput.isSuccessful()) {
244 batchGroups.add(new BatchFailedGroupsOutputBuilder()
246 .setBatchOrder(batchOrder)
248 groupErrors.addAll(groupModOutput.getErrors());
253 final RpcResultBuilder<List<BatchFailedGroupsOutput>> resultBuilder;
254 if (!groupErrors.isEmpty()) {
255 resultBuilder = RpcResultBuilder.<List<BatchFailedGroupsOutput>>failed()
256 .withRpcErrors(groupErrors).withResult(batchGroups);
258 resultBuilder = SUCCESSFUL_GROUP_OUTPUT_RPC_RESULT;
260 return resultBuilder.build();