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.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;
89 * Sample DataTreeChangeListener.
92 @Component(service = { })
93 public final class SampleFlowCapableNodeListener
94 implements ClusteredDataTreeChangeListener<FlowCapableNode>, AutoCloseable {
95 private static final Logger LOG = LoggerFactory.getLogger(SampleFlowCapableNodeListener.class);
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();
101 private final ControlBundle controlBundle;
102 private final AddBundleMessages addBundleMessages;
103 private final Registration listenerReg;
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");
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);
118 listenerReg = dataBroker.registerDataTreeChangeListener(identifier, SampleFlowCapableNodeListener.this);
124 public void close() {
125 LOG.debug("close() passing");
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));
137 new NodeRef(modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class));
139 final var openBundleInput = new ControlBundleInputBuilder()
141 .setBundleId(BUNDLE_ID)
142 .setFlags(BUNDLE_FLAGS)
143 .setType(BundleControlType.ONFBCTOPENREQUEST)
146 final var commitBundleInput = new ControlBundleInputBuilder()
148 .setBundleId(BUNDLE_ID)
149 .setFlags(BUNDLE_FLAGS)
150 .setType(BundleControlType.ONFBCTCOMMITREQUEST)
153 final var innerMessages = createMessages(nodeRef);
154 final var messages = new MessagesBuilder().setMessage(innerMessages).build();
155 final var addBundleMessagesInput = new AddBundleMessagesInputBuilder()
157 .setBundleId(BUNDLE_ID)
158 .setFlags(BUNDLE_FLAGS)
159 .setMessages(messages)
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()));
177 private static <T> CompletableFuture<T> makeCompletableFuture(final Future<T> future) {
178 return CompletableFuture.supplyAsync(() -> {
181 } catch (InterruptedException | ExecutionException e) {
182 throw new IllegalStateException(e);
187 private static List<Message> createMessages(final NodeRef nodeRef) {
188 final var messages = List.of(
191 .setBundleInnerMessage(new BundleAddGroupCaseBuilder()
192 .setAddGroupCaseData(new AddGroupCaseDataBuilder(createGroup(Uint32.ONE)).build()).build())
196 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
198 new AddFlowCaseDataBuilder(createFlow("42", Uint32.ONE, Uint16.ONE, Uint8.ONE)).build())
203 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
205 new AddFlowCaseDataBuilder(createFlow("43", Uint32.ONE, Uint16.TWO, Uint8.TWO)).build())
209 LOG.debug("createMessages() passing {}", messages);
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))
219 .setMatch(new MatchBuilder()
220 .setEthernetMatch(new EthernetMatchBuilder()
221 .setEthernetType(new EthernetTypeBuilder()
222 .setType(new EtherType(Uint32.valueOf(2048)))
226 .setInstructions(createGroupInstructions(groupId).build())
227 .setPriority(priority)
228 .setCookie(new FlowCookie(Uint64.valueOf(flowId + "" + priority)))
229 .setHardTimeout(Uint16.ZERO)
230 .setIdleTimeout(Uint16.ZERO)
232 .setContainerName(null)
233 .setFlowName("FlowWithGroupInstruction")
237 private static Group createGroup(final Uint32 groupId) {
238 return new GroupBuilder()
239 .setGroupId(new GroupId(groupId))
242 .setContainerName(null)
243 .setGroupType(GroupTypes.GroupAll)
244 .setBuckets(createBuckets().build())
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()
254 .setAction(new PopVlanActionCaseBuilder()
255 .setPopVlanAction(new PopVlanActionBuilder().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())
267 .build(), new ActionBuilder()
269 .setAction(new SetFieldCaseBuilder()
270 .setSetField(new SetFieldBuilder()
271 .setLayer3Match(new Ipv4MatchBuilder()
272 .setIpv4Destination(new Ipv4Prefix("10.0.10.0/32"))
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())
290 .withKey(new ActionKey(0))
294 .withKey(new InstructionKey(0))