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.DataBroker;
20 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
21 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
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 implements DataTreeChangeListener<FlowCapableNode>, AutoCloseable {
94 private static final Logger LOG = LoggerFactory.getLogger(SampleFlowCapableNodeListener.class);
96 private static final BundleId BUNDLE_ID = new BundleId(Uint32.ONE);
97 private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true);
98 private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
100 private final ControlBundle controlBundle;
101 private final AddBundleMessages addBundleMessages;
102 private final Registration listenerReg;
106 public SampleFlowCapableNodeListener(@Reference final DataBroker dataBroker,
107 @Reference final RpcService rpcService) {
108 controlBundle = rpcService.getRpc(ControlBundle.class);
109 addBundleMessages = rpcService.getRpc(AddBundleMessages.class);
110 LOG.debug("inSessionInitialized() passing");
112 final InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class)
113 .augmentation(FlowCapableNode.class);
114 final DataTreeIdentifier<FlowCapableNode> identifier =
115 DataTreeIdentifier.of(LogicalDatastoreType.OPERATIONAL, path);
117 listenerReg = dataBroker.registerTreeChangeListener(identifier, SampleFlowCapableNodeListener.this);
123 public void close() {
124 LOG.debug("close() passing");
129 public void onDataTreeChanged(final List<DataTreeModification<FlowCapableNode>> modifications) {
130 for (var modification : modifications) {
131 if (modification.getRootNode().modificationType() == ModificationType.WRITE) {
132 final var nodePath = modification.getRootPath().path().firstIdentifierOf(Node.class);
133 LOG.info("Node connected: {}", nodePath);
135 final var nodeRef = new NodeRef(nodePath);
137 final var openBundleInput = new ControlBundleInputBuilder()
139 .setBundleId(BUNDLE_ID)
140 .setFlags(BUNDLE_FLAGS)
141 .setType(BundleControlType.ONFBCTOPENREQUEST)
144 final var commitBundleInput = new ControlBundleInputBuilder()
146 .setBundleId(BUNDLE_ID)
147 .setFlags(BUNDLE_FLAGS)
148 .setType(BundleControlType.ONFBCTCOMMITREQUEST)
151 final var innerMessages = createMessages(nodeRef);
152 final var messages = new MessagesBuilder().setMessage(innerMessages).build();
153 final var addBundleMessagesInput = new AddBundleMessagesInputBuilder()
155 .setBundleId(BUNDLE_ID)
156 .setFlags(BUNDLE_FLAGS)
157 .setMessages(messages)
160 makeCompletableFuture(controlBundle.invoke(openBundleInput))
161 .thenComposeAsync(voidRpcResult -> {
162 LOG.debug("Open successful: {}, msg: {}", voidRpcResult.isSuccessful(),
163 voidRpcResult.getErrors());
164 return makeCompletableFuture(addBundleMessages.invoke(addBundleMessagesInput));
165 }).thenComposeAsync(voidRpcResult -> {
166 LOG.debug("AddBundleMessages successful: {}, msg: {}", voidRpcResult.isSuccessful(),
167 voidRpcResult.getErrors());
168 return makeCompletableFuture(controlBundle.invoke(commitBundleInput));
169 }).thenAccept(voidRpcResult -> LOG.debug("Commit successful: {}, msg: {}",
170 voidRpcResult.isSuccessful(), voidRpcResult.getErrors()));
175 private static <T> CompletableFuture<T> makeCompletableFuture(final Future<T> future) {
176 return CompletableFuture.supplyAsync(() -> {
179 } catch (InterruptedException | ExecutionException e) {
180 throw new IllegalStateException(e);
185 private static List<Message> createMessages(final NodeRef nodeRef) {
186 final var messages = List.of(
189 .setBundleInnerMessage(new BundleAddGroupCaseBuilder()
190 .setAddGroupCaseData(new AddGroupCaseDataBuilder(createGroup(Uint32.ONE)).build()).build())
194 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
196 new AddFlowCaseDataBuilder(createFlow("42", Uint32.ONE, Uint16.ONE, Uint8.ONE)).build())
201 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
203 new AddFlowCaseDataBuilder(createFlow("43", Uint32.ONE, Uint16.TWO, Uint8.TWO)).build())
207 LOG.debug("createMessages() passing {}", messages);
212 private static Flow createFlow(final String flowId, final Uint32 groupId, final Uint16 priority,
213 final Uint8 tableId) {
214 return new FlowBuilder()
215 .setId(new FlowId(flowId))
217 .setMatch(new MatchBuilder()
218 .setEthernetMatch(new EthernetMatchBuilder()
219 .setEthernetType(new EthernetTypeBuilder()
220 .setType(new EtherType(Uint32.valueOf(2048)))
224 .setInstructions(createGroupInstructions(groupId).build())
225 .setPriority(priority)
226 .setCookie(new FlowCookie(Uint64.valueOf(flowId + "" + priority)))
227 .setHardTimeout(Uint16.ZERO)
228 .setIdleTimeout(Uint16.ZERO)
230 .setContainerName(null)
231 .setFlowName("FlowWithGroupInstruction")
235 private static Group createGroup(final Uint32 groupId) {
236 return new GroupBuilder()
237 .setGroupId(new GroupId(groupId))
240 .setContainerName(null)
241 .setGroupType(GroupTypes.GroupAll)
242 .setBuckets(createBuckets().build())
246 private static BucketsBuilder createBuckets() {
247 return new BucketsBuilder()
248 .setBucket(BindingMap.ordered(new BucketBuilder()
249 .setBucketId(new BucketId(Uint32.valueOf(12)))
250 .setAction(BindingMap.of(new ActionBuilder()
252 .setAction(new PopVlanActionCaseBuilder()
253 .setPopVlanAction(new PopVlanActionBuilder().build())
256 .build(), new BucketBuilder()
257 .setBucketId(new BucketId(Uint32.valueOf(13)))
258 .setAction(BindingMap.of(new ActionBuilder()
259 .setAction(new SetFieldCaseBuilder()
260 .setSetField(new SetFieldBuilder()
261 .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix("10.0.1.0/32")).build())
265 .build(), new ActionBuilder()
267 .setAction(new SetFieldCaseBuilder()
268 .setSetField(new SetFieldBuilder()
269 .setLayer3Match(new Ipv4MatchBuilder()
270 .setIpv4Destination(new Ipv4Prefix("10.0.10.0/32"))
278 private static InstructionsBuilder createGroupInstructions(final Uint32 groupId) {
279 return new InstructionsBuilder()
280 .setInstruction(BindingMap.of(new InstructionBuilder()
281 .setInstruction(new ApplyActionsCaseBuilder()
282 .setApplyActions(new ApplyActionsBuilder()
283 .setAction(BindingMap.of(new ActionBuilder()
284 .setAction(new GroupActionCaseBuilder()
285 .setGroupAction(new GroupActionBuilder().setGroupId(groupId).build())
288 .withKey(new ActionKey(0))
292 .withKey(new InstructionKey(0))