Bump upstreams
[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.util.List;
11 import java.util.concurrent.CompletableFuture;
12 import java.util.concurrent.ExecutionException;
13 import java.util.concurrent.ExecutorService;
14 import java.util.concurrent.Executors;
15 import java.util.concurrent.Future;
16 import javax.annotation.PreDestroy;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
20 import org.opendaylight.mdsal.binding.api.DataBroker;
21 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
22 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
23 import org.opendaylight.mdsal.binding.api.DataTreeModification;
24 import org.opendaylight.mdsal.binding.api.RpcService;
25 import org.opendaylight.mdsal.common.api.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.ActionBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessages;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundle;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.MessagesBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.Message;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.MessageBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddFlowCaseBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddGroupCaseBuilder;
69 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;
70 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;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleControlType;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleFlags;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId;
74 import org.opendaylight.yangtools.concepts.Registration;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
76 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
77 import org.opendaylight.yangtools.yang.common.Uint16;
78 import org.opendaylight.yangtools.yang.common.Uint32;
79 import org.opendaylight.yangtools.yang.common.Uint64;
80 import org.opendaylight.yangtools.yang.common.Uint8;
81 import org.osgi.service.component.annotations.Activate;
82 import org.osgi.service.component.annotations.Component;
83 import org.osgi.service.component.annotations.Deactivate;
84 import org.osgi.service.component.annotations.Reference;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
87
88 /**
89  * Sample DataTreeChangeListener.
90  */
91 @Singleton
92 @Component(service = { })
93 public final class SampleFlowCapableNodeListener
94         implements ClusteredDataTreeChangeListener<FlowCapableNode>, AutoCloseable {
95     private static final Logger LOG = LoggerFactory.getLogger(SampleFlowCapableNodeListener.class);
96
97     private static final BundleId BUNDLE_ID = new BundleId(Uint32.ONE);
98     private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true);
99     private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
100
101     private final ControlBundle controlBundle;
102     private final AddBundleMessages addBundleMessages;
103     private final Registration listenerReg;
104
105     @Inject
106     @Activate
107     public SampleFlowCapableNodeListener(@Reference final DataBroker dataBroker,
108             @Reference final RpcService rpcService) {
109         controlBundle = rpcService.getRpc(ControlBundle.class);
110         addBundleMessages = rpcService.getRpc(AddBundleMessages.class);
111         LOG.debug("inSessionInitialized() passing");
112
113         final InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class)
114                 .augmentation(FlowCapableNode.class);
115         final DataTreeIdentifier<FlowCapableNode> identifier =
116                 DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, path);
117
118         listenerReg = dataBroker.registerDataTreeChangeListener(identifier, SampleFlowCapableNodeListener.this);
119     }
120
121     @PreDestroy
122     @Deactivate
123     @Override
124     public void close() {
125         LOG.debug("close() passing");
126         listenerReg.close();
127     }
128
129     @Override
130     public void onDataTreeChanged(final List<DataTreeModification<FlowCapableNode>> modifications) {
131         for (var modification : modifications) {
132             if (modification.getRootNode().getModificationType() == ModificationType.WRITE) {
133                 LOG.info("Node connected:  {}",
134                         modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class));
135
136                 final var nodeRef =
137                         new NodeRef(modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class));
138
139                 final var openBundleInput = new ControlBundleInputBuilder()
140                         .setNode(nodeRef)
141                         .setBundleId(BUNDLE_ID)
142                         .setFlags(BUNDLE_FLAGS)
143                         .setType(BundleControlType.ONFBCTOPENREQUEST)
144                         .build();
145
146                 final var commitBundleInput = new ControlBundleInputBuilder()
147                         .setNode(nodeRef)
148                         .setBundleId(BUNDLE_ID)
149                         .setFlags(BUNDLE_FLAGS)
150                         .setType(BundleControlType.ONFBCTCOMMITREQUEST)
151                         .build();
152
153                 final var innerMessages = createMessages(nodeRef);
154                 final var messages = new MessagesBuilder().setMessage(innerMessages).build();
155                 final var addBundleMessagesInput = new AddBundleMessagesInputBuilder()
156                         .setNode(nodeRef)
157                         .setBundleId(BUNDLE_ID)
158                         .setFlags(BUNDLE_FLAGS)
159                         .setMessages(messages)
160                         .build();
161
162                 makeCompletableFuture(controlBundle.invoke(openBundleInput))
163                     .thenComposeAsync(voidRpcResult -> {
164                         LOG.debug("Open successful: {}, msg: {}", voidRpcResult.isSuccessful(),
165                                 voidRpcResult.getErrors());
166                         return makeCompletableFuture(addBundleMessages.invoke(addBundleMessagesInput));
167                     }).thenComposeAsync(voidRpcResult -> {
168                         LOG.debug("AddBundleMessages successful: {}, msg: {}", voidRpcResult.isSuccessful(),
169                                 voidRpcResult.getErrors());
170                         return makeCompletableFuture(controlBundle.invoke(commitBundleInput));
171                     }).thenAccept(voidRpcResult -> LOG.debug("Commit successful: {}, msg: {}",
172                         voidRpcResult.isSuccessful(), voidRpcResult.getErrors()));
173             }
174         }
175     }
176
177     private static <T> CompletableFuture<T> makeCompletableFuture(final Future<T> future) {
178         return CompletableFuture.supplyAsync(() -> {
179             try {
180                 return future.get();
181             } catch (InterruptedException | ExecutionException e) {
182                 throw new IllegalStateException(e);
183             }
184         }, EXECUTOR);
185     }
186
187     private static List<Message> createMessages(final NodeRef nodeRef) {
188         final var messages = List.of(
189             new MessageBuilder()
190                 .setNode(nodeRef)
191                 .setBundleInnerMessage(new BundleAddGroupCaseBuilder()
192                     .setAddGroupCaseData(new AddGroupCaseDataBuilder(createGroup(Uint32.ONE)).build()).build())
193                 .build(),
194             new MessageBuilder()
195                 .setNode(nodeRef)
196                 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
197                     .setAddFlowCaseData(
198                         new AddFlowCaseDataBuilder(createFlow("42", Uint32.ONE, Uint16.ONE, Uint8.ONE)).build())
199                     .build())
200                 .build(),
201             new MessageBuilder()
202                 .setNode(nodeRef)
203                 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
204                     .setAddFlowCaseData(
205                         new AddFlowCaseDataBuilder(createFlow("43", Uint32.ONE, Uint16.TWO, Uint8.TWO)).build())
206                     .build())
207                 .build());
208
209         LOG.debug("createMessages() passing {}", messages);
210
211         return messages;
212     }
213
214     private static Flow createFlow(final String flowId, final Uint32 groupId, final Uint16 priority,
215             final Uint8 tableId) {
216         return new FlowBuilder()
217             .setId(new FlowId(flowId))
218             .setTableId(tableId)
219             .setMatch(new MatchBuilder()
220                 .setEthernetMatch(new EthernetMatchBuilder()
221                     .setEthernetType(new EthernetTypeBuilder()
222                         .setType(new EtherType(Uint32.valueOf(2048)))
223                         .build())
224                     .build())
225                 .build())
226             .setInstructions(createGroupInstructions(groupId).build())
227             .setPriority(priority)
228             .setCookie(new FlowCookie(Uint64.valueOf(flowId + "" + priority)))
229             .setHardTimeout(Uint16.ZERO)
230             .setIdleTimeout(Uint16.ZERO)
231             .setStrict(false)
232             .setContainerName(null)
233             .setFlowName("FlowWithGroupInstruction")
234             .build();
235     }
236
237     private static Group createGroup(final Uint32 groupId) {
238         return new GroupBuilder()
239             .setGroupId(new GroupId(groupId))
240             .setBarrier(false)
241             .setGroupName("Foo")
242             .setContainerName(null)
243             .setGroupType(GroupTypes.GroupAll)
244             .setBuckets(createBuckets().build())
245             .build();
246     }
247
248     private static BucketsBuilder createBuckets() {
249         return new BucketsBuilder()
250             .setBucket(BindingMap.ordered(new BucketBuilder()
251                 .setBucketId(new BucketId(Uint32.valueOf(12)))
252                 .setAction(BindingMap.of(new ActionBuilder()
253                     .setOrder(0)
254                     .setAction(new PopVlanActionCaseBuilder()
255                         .setPopVlanAction(new PopVlanActionBuilder().build())
256                         .build())
257                     .build()))
258                 .build(), new BucketBuilder()
259                 .setBucketId(new BucketId(Uint32.valueOf(13)))
260                 .setAction(BindingMap.of(new ActionBuilder()
261                     .setAction(new SetFieldCaseBuilder()
262                         .setSetField(new SetFieldBuilder()
263                             .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix("10.0.1.0/32")).build())
264                             .build())
265                         .build())
266                     .setOrder(0)
267                     .build(), new ActionBuilder()
268                     .setOrder(0)
269                     .setAction(new SetFieldCaseBuilder()
270                         .setSetField(new SetFieldBuilder()
271                             .setLayer3Match(new Ipv4MatchBuilder()
272                                 .setIpv4Destination(new Ipv4Prefix("10.0.10.0/32"))
273                                 .build())
274                             .build())
275                         .build())
276                     .build()))
277                 .build()));
278     }
279
280     private static InstructionsBuilder createGroupInstructions(final Uint32 groupId) {
281         return new InstructionsBuilder()
282             .setInstruction(BindingMap.of(new InstructionBuilder()
283                 .setInstruction(new ApplyActionsCaseBuilder()
284                     .setApplyActions(new ApplyActionsBuilder()
285                         .setAction(BindingMap.of(new ActionBuilder()
286                             .setAction(new GroupActionCaseBuilder()
287                                 .setGroupAction(new GroupActionBuilder().setGroupId(groupId).build())
288                                 .build())
289                             .setOrder(1)
290                             .withKey(new ActionKey(0))
291                             .build()))
292                         .build())
293                     .build())
294                 .withKey(new InstructionKey(0))
295                 .build()));
296     }
297 }