2 * Copyright (c) 2017 Pantheon Technologies s.r.o. 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
8 package org.opendaylight.openflowplugin.samples.sample.bundles;
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.concurrent.CompletableFuture;
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.ExecutorService;
16 import java.util.concurrent.Executors;
17 import java.util.concurrent.Future;
18 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
19 import org.opendaylight.mdsal.binding.api.DataBroker;
20 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
21 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.mdsal.binding.api.DataTreeModification;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInputBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesOutput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleInputBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleOutput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.SalBundleService;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.Messages;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.MessagesBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.Message;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.MessageBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddFlowCaseBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddGroupCaseBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.bundle.add.flow._case.AddFlowCaseDataBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.bundle.add.group._case.AddGroupCaseDataBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleControlType;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleFlags;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId;
76 import org.opendaylight.yangtools.concepts.ListenerRegistration;
77 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
78 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
79 import org.opendaylight.yangtools.yang.common.RpcResult;
80 import org.opendaylight.yangtools.yang.common.Uint16;
81 import org.opendaylight.yangtools.yang.common.Uint32;
82 import org.opendaylight.yangtools.yang.common.Uint64;
83 import org.opendaylight.yangtools.yang.common.Uint8;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
88 * Sample DataTreeChangeListener.
90 public class SampleFlowCapableNodeListener implements ClusteredDataTreeChangeListener<FlowCapableNode>, AutoCloseable {
92 private static final Logger LOG = LoggerFactory.getLogger(SampleFlowCapableNodeListener.class);
94 private static final BundleId BUNDLE_ID = new BundleId(Uint32.ONE);
95 private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true);
96 private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
98 private final DataBroker dataBroker;
99 private final SalBundleService bundleService;
100 private ListenerRegistration<?> listenerReg;
102 public SampleFlowCapableNodeListener(final DataBroker dataBroker, final SalBundleService bundleService) {
103 this.dataBroker = dataBroker;
104 this.bundleService = bundleService;
108 public void close() {
109 LOG.debug("close() passing");
110 if (listenerReg != null) {
116 LOG.debug("inSessionInitialized() passing");
118 final InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class)
119 .augmentation(FlowCapableNode.class);
120 final DataTreeIdentifier<FlowCapableNode> identifier =
121 DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, path);
123 listenerReg = dataBroker.registerDataTreeChangeListener(identifier, SampleFlowCapableNodeListener.this);
127 public void onDataTreeChanged(final Collection<DataTreeModification<FlowCapableNode>> modifications) {
128 for (DataTreeModification<FlowCapableNode> modification : modifications) {
129 if (modification.getRootNode().getModificationType() == ModificationType.WRITE) {
130 LOG.info("Node connected: {}",
131 modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class));
133 final NodeRef nodeRef =
134 new NodeRef(modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class));
136 final ControlBundleInput openBundleInput = new ControlBundleInputBuilder()
138 .setBundleId(BUNDLE_ID)
139 .setFlags(BUNDLE_FLAGS)
140 .setType(BundleControlType.ONFBCTOPENREQUEST)
143 final ControlBundleInput commitBundleInput = new ControlBundleInputBuilder()
145 .setBundleId(BUNDLE_ID)
146 .setFlags(BUNDLE_FLAGS)
147 .setType(BundleControlType.ONFBCTCOMMITREQUEST)
150 final List<Message> innerMessages = createMessages(nodeRef);
151 final Messages messages = new MessagesBuilder().setMessage(innerMessages).build();
152 final AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
154 .setBundleId(BUNDLE_ID)
155 .setFlags(BUNDLE_FLAGS)
156 .setMessages(messages)
159 makeCompletableFuture(bundleService.controlBundle(openBundleInput))
160 .thenComposeAsync(voidRpcResult -> {
161 LOG.debug("Open successful: {}, msg: {}", voidRpcResult.isSuccessful(),
162 voidRpcResult.getErrors());
164 final CompletableFuture<RpcResult<AddBundleMessagesOutput>> addFuture =
165 makeCompletableFuture(bundleService.addBundleMessages(addBundleMessagesInput));
168 }).thenComposeAsync(voidRpcResult -> {
169 LOG.debug("AddBundleMessages successful: {}, msg: {}", voidRpcResult.isSuccessful(),
170 voidRpcResult.getErrors());
172 final CompletableFuture<RpcResult<ControlBundleOutput>> controlCommitFuture =
173 makeCompletableFuture(bundleService.controlBundle(commitBundleInput));
175 return controlCommitFuture;
176 }).thenAccept(voidRpcResult -> LOG.debug("Commit successful: {}, msg: {}",
177 voidRpcResult.isSuccessful(), voidRpcResult.getErrors()));
182 private static <T> CompletableFuture<T> makeCompletableFuture(final Future<T> future) {
183 return CompletableFuture.supplyAsync(() -> {
186 } catch (InterruptedException | ExecutionException e) {
187 throw new RuntimeException(e);
192 private static List<Message> createMessages(final NodeRef nodeRef) {
193 List<Message> messages = new ArrayList<>();
196 messages.add(new MessageBuilder()
198 .setBundleInnerMessage(new BundleAddGroupCaseBuilder()
199 .setAddGroupCaseData(new AddGroupCaseDataBuilder(createGroup(Uint32.ONE)).build()).build())
202 messages.add(new MessageBuilder()
204 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
205 .setAddFlowCaseData(new AddFlowCaseDataBuilder(createFlow("42", Uint32.ONE, Uint16.ONE, Uint8.ONE))
210 messages.add(new MessageBuilder()
212 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
213 .setAddFlowCaseData(new AddFlowCaseDataBuilder(createFlow("43", Uint32.ONE, Uint16.TWO, Uint8.TWO))
218 LOG.debug("createMessages() passing {}", messages);
223 private static Flow createFlow(final String flowId, final Uint32 groupId, final Uint16 priority,
224 final Uint8 tableId) {
225 return new FlowBuilder()
226 .setId(new FlowId(flowId))
228 .setMatch(new MatchBuilder()
229 .setEthernetMatch(new EthernetMatchBuilder()
230 .setEthernetType(new EthernetTypeBuilder()
231 .setType(new EtherType(Uint32.valueOf(2048)))
235 .setInstructions(createGroupInstructions(groupId).build())
236 .setPriority(priority)
237 .setCookie(new FlowCookie(Uint64.valueOf(flowId + "" + priority)))
238 .setHardTimeout(Uint16.ZERO)
239 .setIdleTimeout(Uint16.ZERO)
241 .setContainerName(null)
242 .setFlowName("FlowWithGroupInstruction")
246 private static Group createGroup(final Uint32 groupId) {
247 return new GroupBuilder()
248 .setGroupId(new GroupId(groupId))
251 .setContainerName(null)
252 .setGroupType(GroupTypes.GroupAll)
253 .setBuckets(createBuckets().build())
257 private static BucketsBuilder createBuckets() {
258 return new BucketsBuilder()
259 .setBucket(BindingMap.ordered(new BucketBuilder()
260 .setBucketId(new BucketId(Uint32.valueOf(12)))
261 .setAction(BindingMap.of(new ActionBuilder()
263 .setAction(new PopVlanActionCaseBuilder()
264 .setPopVlanAction(new PopVlanActionBuilder().build())
267 .build(), new BucketBuilder()
268 .setBucketId(new BucketId(Uint32.valueOf(13)))
269 .setAction(BindingMap.of(new ActionBuilder()
270 .setAction(new SetFieldCaseBuilder()
271 .setSetField(new SetFieldBuilder()
272 .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix("10.0.1.0/32")).build())
276 .build(), new ActionBuilder()
278 .setAction(new SetFieldCaseBuilder()
279 .setSetField(new SetFieldBuilder()
280 .setLayer3Match(new Ipv4MatchBuilder()
281 .setIpv4Destination(new Ipv4Prefix("10.0.10.0/32"))
289 private static InstructionsBuilder createGroupInstructions(final Uint32 groupId) {
290 return new InstructionsBuilder()
291 .setInstruction(BindingMap.of(new InstructionBuilder()
292 .setInstruction(new ApplyActionsCaseBuilder()
293 .setApplyActions(new ApplyActionsBuilder()
294 .setAction(BindingMap.of(new ActionBuilder()
295 .setAction(new GroupActionCaseBuilder()
296 .setGroupAction(new GroupActionBuilder().setGroupId(groupId).build())
299 .withKey(new ActionKey(0))
303 .withKey(new InstructionKey(0))