b81f3ef005e15786ad778dfcd9809913bcd4502c
[openflowplugin.git] / samples / sample-bundles / src / main / java / org / opendaylight / openflowplugin / samples / sample / bundles / SampleFlowCapableNodeListener.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.openflowplugin.samples.sample.bundles;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
14 import java.util.concurrent.CompletableFuture;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.ExecutorService;
17 import java.util.concurrent.Executors;
18 import java.util.concurrent.Future;
19 import javax.annotation.Nonnull;
20 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
24 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesOutput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.SalBundleService;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.Messages;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.MessagesBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.Message;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.MessageBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddFlowCaseBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddGroupCaseBuilder;
78 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;
79 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;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleControlType;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleFlags;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId;
83 import org.opendaylight.yangtools.concepts.ListenerRegistration;
84 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
85 import org.opendaylight.yangtools.yang.common.RpcResult;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
88
89 /**
90  * Sample DataTreeChangeListener.
91  */
92 public class SampleFlowCapableNodeListener implements ClusteredDataTreeChangeListener<FlowCapableNode>, AutoCloseable {
93
94     private static final Logger LOG = LoggerFactory.getLogger(SampleFlowCapableNodeListener.class);
95
96     private static final BundleId BUNDLE_ID = new BundleId(1L);
97     private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true);
98     private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
99
100     private final DataBroker dataBroker;
101     private final SalBundleService bundleService;
102     private ListenerRegistration<?> listenerReg;
103
104     public SampleFlowCapableNodeListener(DataBroker dataBroker, SalBundleService bundleService) {
105         this.dataBroker = dataBroker;
106         this.bundleService = bundleService;
107     }
108
109     @Override
110     public void close() {
111         LOG.debug("close() passing");
112         if (listenerReg != null) {
113             listenerReg.close();
114         }
115     }
116
117     public void init() {
118         LOG.debug("inSessionInitialized() passing");
119
120         final InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class)
121                 .augmentation(FlowCapableNode.class);
122         final DataTreeIdentifier<FlowCapableNode> identifier =
123                 new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, path);
124
125         listenerReg = dataBroker.registerDataTreeChangeListener(identifier, SampleFlowCapableNodeListener.this);
126     }
127
128     @Override
129     public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<FlowCapableNode>> modifications) {
130         for (DataTreeModification<FlowCapableNode> modification : modifications) {
131             if (modification.getRootNode().getModificationType() == ModificationType.WRITE) {
132                 LOG.info("Node connected:  {}",
133                         modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class));
134
135                 final NodeRef nodeRef =
136                         new NodeRef(modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class));
137
138                 final ControlBundleInput openBundleInput = new ControlBundleInputBuilder()
139                         .setNode(nodeRef)
140                         .setBundleId(BUNDLE_ID)
141                         .setFlags(BUNDLE_FLAGS)
142                         .setType(BundleControlType.ONFBCTOPENREQUEST)
143                         .build();
144
145                 final ControlBundleInput commitBundleInput = new ControlBundleInputBuilder()
146                         .setNode(nodeRef)
147                         .setBundleId(BUNDLE_ID)
148                         .setFlags(BUNDLE_FLAGS)
149                         .setType(BundleControlType.ONFBCTCOMMITREQUEST)
150                         .build();
151
152                 final List<Message> innerMessages = createMessages(nodeRef);
153                 final Messages messages = new MessagesBuilder().setMessage(innerMessages).build();
154                 final AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
155                         .setNode(nodeRef)
156                         .setBundleId(BUNDLE_ID)
157                         .setFlags(BUNDLE_FLAGS)
158                         .setMessages(messages)
159                         .build();
160
161                 makeCompletableFuture(bundleService.controlBundle(openBundleInput))
162                     .thenComposeAsync(voidRpcResult -> {
163                         LOG.debug("Open successful: {}, msg: {}", voidRpcResult.isSuccessful(),
164                                 voidRpcResult.getErrors());
165
166                         final CompletableFuture<RpcResult<AddBundleMessagesOutput>> addFuture =
167                                 makeCompletableFuture(bundleService.addBundleMessages(addBundleMessagesInput));
168
169                         return addFuture;
170                     }).thenComposeAsync(voidRpcResult -> {
171                         LOG.debug("AddBundleMessages successful: {}, msg: {}", voidRpcResult.isSuccessful(),
172                                 voidRpcResult.getErrors());
173
174                         final CompletableFuture<RpcResult<ControlBundleOutput>> controlCommitFuture =
175                                 makeCompletableFuture(bundleService.controlBundle(commitBundleInput));
176
177                         return controlCommitFuture;
178                     }).thenAccept(voidRpcResult -> LOG.debug("Commit successful: {}, msg: {}",
179                         voidRpcResult.isSuccessful(), voidRpcResult.getErrors()));
180             }
181         }
182     }
183
184     private static <T> CompletableFuture<T> makeCompletableFuture(Future<T> future) {
185         return CompletableFuture.supplyAsync(() -> {
186             try {
187                 return future.get();
188             } catch (InterruptedException | ExecutionException e) {
189                 throw new RuntimeException(e);
190             }
191         }, EXECUTOR);
192     }
193
194     private static List<Message> createMessages(NodeRef nodeRef) {
195         List<Message> messages  = new ArrayList<>();
196
197
198         messages.add(new MessageBuilder().setNode(nodeRef).setBundleInnerMessage(new BundleAddGroupCaseBuilder()
199             .setAddGroupCaseData(new AddGroupCaseDataBuilder(createGroup(1L)).build()).build()).build());
200
201         messages.add(new MessageBuilder().setNode(nodeRef).setBundleInnerMessage(new BundleAddFlowCaseBuilder()
202                 .setAddFlowCaseData(new AddFlowCaseDataBuilder(createFlow("42", 1L, 1, (short) 1)).build()).build())
203                 .build());
204
205         messages.add(new MessageBuilder().setNode(nodeRef).setBundleInnerMessage(new BundleAddFlowCaseBuilder()
206                 .setAddFlowCaseData(new AddFlowCaseDataBuilder(createFlow("43", 1L, 2, (short) 2)).build()).build())
207                 .build());
208
209         LOG.debug("createMessages() passing {}", messages);
210
211         return messages;
212     }
213
214     private static Flow createFlow(String flowId, long groupId, int priority, short tableId) {
215         MatchBuilder matchBuilder = new MatchBuilder();
216         matchBuilder.setEthernetMatch(new EthernetMatchBuilder()
217                 .setEthernetType(new EthernetTypeBuilder()
218                         .setType(new EtherType(2048L)).build()).build());
219
220         FlowBuilder flowBuilder = new FlowBuilder();
221         flowBuilder.setMatch(matchBuilder.build());
222         flowBuilder.setInstructions(createGroupInstructions(groupId).build());
223         flowBuilder.setPriority(priority);
224         flowBuilder.setCookie(new FlowCookie(new BigInteger(flowId + "" + priority)));
225
226         FlowKey key = new FlowKey(new FlowId(flowId));
227         flowBuilder.setHardTimeout(0);
228         flowBuilder.setIdleTimeout(0);
229         flowBuilder.setStrict(false);
230         flowBuilder.setContainerName(null);
231         flowBuilder.setId(new FlowId(flowId));
232         flowBuilder.setTableId(tableId);
233         flowBuilder.withKey(key);
234         flowBuilder.setFlowName("FlowWithGroupInstruction");
235
236         return flowBuilder.build();
237     }
238
239     private static Group createGroup(long groupId) {
240         GroupBuilder groupBuilder = new GroupBuilder();
241         GroupKey groupKey = new GroupKey(new GroupId(groupId));
242         groupBuilder.withKey(groupKey);
243         groupBuilder.setGroupId(groupKey.getGroupId());
244         groupBuilder.setBarrier(false);
245         groupBuilder.setGroupName("Foo");
246         groupBuilder.setContainerName(null);
247         groupBuilder.setGroupType(GroupTypes.GroupAll);
248         groupBuilder.setBuckets(createBuckets().build());
249
250         return groupBuilder.build();
251     }
252
253     private static BucketsBuilder createBuckets() {
254         List<Action> actionList = new ArrayList<>();
255
256         actionList.add(new ActionBuilder()
257                 .setOrder(0)
258                 .setAction(new PopVlanActionCaseBuilder()
259                         .setPopVlanAction(new PopVlanActionBuilder().build())
260                         .build()).build());
261
262         BucketBuilder bucketBuilder = new BucketBuilder();
263         bucketBuilder.setBucketId(new BucketId(12L));
264         bucketBuilder.setAction(actionList);
265
266         List<Bucket> bucketList = new ArrayList<>();
267         bucketList.add(bucketBuilder.build());
268
269         actionList = new ArrayList<>();
270         SetFieldCaseBuilder setFieldCaseBuilder = new SetFieldCaseBuilder();
271         setFieldCaseBuilder.setSetField(new SetFieldBuilder()
272                 .setLayer3Match(new Ipv4MatchBuilder()
273                         .setIpv4Source(new Ipv4Prefix("10.0.1.0/32"))
274                         .build())
275                 .build());
276
277         actionList.add(new ActionBuilder()
278                 .setAction(setFieldCaseBuilder.build())
279                 .setOrder(0)
280                 .build());
281
282         setFieldCaseBuilder = new SetFieldCaseBuilder();
283         setFieldCaseBuilder.setSetField(new SetFieldBuilder()
284                 .setLayer3Match(new Ipv4MatchBuilder()
285                         .setIpv4Destination(new Ipv4Prefix("10.0.10.0/32"))
286                         .build())
287                 .build());
288
289         actionList.add(new ActionBuilder()
290                 .setAction(setFieldCaseBuilder.build())
291                 .setOrder(0)
292                 .build());
293
294         bucketBuilder = new BucketBuilder();
295         bucketBuilder.setBucketId(new BucketId(13L));
296         bucketBuilder.setAction(actionList);
297
298         bucketList.add(bucketBuilder.build());
299
300         BucketsBuilder bucketsBuilder = new BucketsBuilder();
301         bucketsBuilder.setBucket(bucketList);
302
303         return bucketsBuilder;
304     }
305
306     private static InstructionsBuilder createGroupInstructions(long groupId) {
307         ActionBuilder actionBuilder = new ActionBuilder();
308
309         GroupActionBuilder groupActionBuilder = new GroupActionBuilder();
310         groupActionBuilder.setGroupId(groupId);
311
312         actionBuilder.setAction(new GroupActionCaseBuilder().setGroupAction(groupActionBuilder.build()).build());
313         actionBuilder.setOrder(1);
314         actionBuilder.withKey(new ActionKey(0));
315         List<Action> actionList = new ArrayList<>();
316         actionList.add(actionBuilder.build());
317
318         ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
319         applyActionsBuilder.setAction(actionList);
320
321         InstructionBuilder instructionBuilder = new InstructionBuilder();
322         instructionBuilder.setInstruction(new ApplyActionsCaseBuilder()
323                 .setApplyActions(applyActionsBuilder.build()).build());
324         instructionBuilder.setOrder(0);
325         instructionBuilder.withKey(new InstructionKey(0));
326
327         InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
328         List<Instruction> instructions = new ArrayList<>();
329         instructions.add(instructionBuilder.build());
330         instructionsBuilder.setInstruction(instructions);
331
332         return instructionsBuilder;
333     }
334 }