/* * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowplugin.samples.sample.bundles; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType; import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.sal.binding.api.AbstractBrokerAwareActivator; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.SalBundleService; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.Messages; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.MessagesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.Message; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.MessageBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddFlowCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddGroupCaseBuilder; 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; 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; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleControlType; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleFlags; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Sample bundles activator. */ public class Activator extends AbstractBrokerAwareActivator implements BindingAwareConsumer, ClusteredDataTreeChangeListener, AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(Activator.class); private static final BundleId BUNDLE_ID = new BundleId(1L); private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true); private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(); private DataBroker dataBroker; private SalBundleService bundleService; @Override public void close() throws Exception { LOG.debug("close() passing"); } @Override public void onSessionInitialized(ConsumerContext consumerContext) { LOG.debug("inSessionInitialized() passing"); dataBroker = consumerContext.getSALService(DataBroker.class); final InstanceIdentifier path = InstanceIdentifier.create(Nodes.class).child(Node.class) .augmentation(FlowCapableNode.class); final DataTreeIdentifier identifier = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, path); dataBroker.registerDataTreeChangeListener(identifier, Activator.this); bundleService = consumerContext.getRpcService(SalBundleService.class); } @Override public void onDataTreeChanged(@Nonnull Collection> modifications) { for (DataTreeModification modification : modifications) { if (modification.getRootNode().getModificationType() == ModificationType.WRITE) { LOG.info("Node connected: {}", modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class)); final NodeRef nodeRef = new NodeRef(modification.getRootPath().getRootIdentifier().firstIdentifierOf(Node.class)); final ControlBundleInput openBundleInput = new ControlBundleInputBuilder() .setNode(nodeRef) .setBundleId(BUNDLE_ID) .setFlags(BUNDLE_FLAGS) .setType(BundleControlType.ONFBCTOPENREQUEST) .build(); final ControlBundleInput commitBundleInput = new ControlBundleInputBuilder() .setNode(nodeRef) .setBundleId(BUNDLE_ID) .setFlags(BUNDLE_FLAGS) .setType(BundleControlType.ONFBCTCOMMITREQUEST) .build(); final List innerMessages = createMessages(nodeRef); final Messages messages = new MessagesBuilder().setMessage(innerMessages).build(); final AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder() .setNode(nodeRef) .setBundleId(BUNDLE_ID) .setFlags(BUNDLE_FLAGS) .setMessages(messages) .build(); makeCompletableFuture(bundleService.controlBundle(openBundleInput)) .thenComposeAsync(voidRpcResult -> { LOG.debug("Open successful: {}, msg: {}", voidRpcResult.isSuccessful(), voidRpcResult.getErrors()); final CompletableFuture> addFuture = makeCompletableFuture(bundleService.addBundleMessages(addBundleMessagesInput)); return addFuture; }).thenComposeAsync(voidRpcResult -> { LOG.debug("AddBundleMessages successful: {}, msg: {}", voidRpcResult.isSuccessful(), voidRpcResult.getErrors()); final CompletableFuture> controlCommitFuture = makeCompletableFuture(bundleService.controlBundle(commitBundleInput)); return controlCommitFuture; }).thenAccept(voidRpcResult -> { LOG.debug("Commit successful: {}, msg: {}", voidRpcResult.isSuccessful(), voidRpcResult.getErrors()); }); } } } private static CompletableFuture makeCompletableFuture(Future future) { return CompletableFuture.supplyAsync(() -> { try { return future.get(); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } }, EXECUTOR); } @Override protected void onBrokerAvailable(BindingAwareBroker bindingAwareBroker, BundleContext bundleContext) { LOG.debug("onBrokerAvailable() passing"); bindingAwareBroker.registerConsumer(this); } private static List createMessages(NodeRef nodeRef) { List messages = new ArrayList<>(); messages.add(new MessageBuilder().setNode(nodeRef).setBundleInnerMessage(new BundleAddGroupCaseBuilder() .setAddGroupCaseData(new AddGroupCaseDataBuilder(createGroup(1L)).build()).build()).build()); messages.add(new MessageBuilder().setNode(nodeRef).setBundleInnerMessage(new BundleAddFlowCaseBuilder() .setAddFlowCaseData(new AddFlowCaseDataBuilder(createFlow("42", 1L, 1, (short) 1)).build()).build()) .build()); messages.add(new MessageBuilder().setNode(nodeRef).setBundleInnerMessage(new BundleAddFlowCaseBuilder() .setAddFlowCaseData(new AddFlowCaseDataBuilder(createFlow("43", 1L, 2, (short) 2)).build()).build()) .build()); LOG.debug("createMessages() passing {}", messages); return messages; } private static Flow createFlow(String flowId, long groupId, int priority, short tableId) { MatchBuilder matchBuilder = new MatchBuilder(); matchBuilder.setEthernetMatch(new EthernetMatchBuilder() .setEthernetType(new EthernetTypeBuilder() .setType(new EtherType(2048L)).build()).build()); FlowBuilder flowBuilder = new FlowBuilder(); flowBuilder.setMatch(matchBuilder.build()); flowBuilder.setInstructions(createGroupInstructions(groupId).build()); flowBuilder.setPriority(priority); flowBuilder.setCookie(new FlowCookie(new BigInteger(flowId + "" + priority))); FlowKey key = new FlowKey(new FlowId(flowId)); flowBuilder.setHardTimeout(0); flowBuilder.setIdleTimeout(0); flowBuilder.setStrict(false); flowBuilder.setContainerName(null); flowBuilder.setId(new FlowId(flowId)); flowBuilder.setTableId(tableId); flowBuilder.setKey(key); flowBuilder.setFlowName("FlowWithGroupInstruction"); return flowBuilder.build(); } private static Group createGroup(long groupId) { GroupBuilder groupBuilder = new GroupBuilder(); GroupKey groupKey = new GroupKey(new GroupId(groupId)); groupBuilder.setKey(groupKey); groupBuilder.setGroupId(groupKey.getGroupId()); groupBuilder.setBarrier(false); groupBuilder.setGroupName("Foo"); groupBuilder.setContainerName(null); groupBuilder.setGroupType(GroupTypes.GroupAll); groupBuilder.setBuckets(createBuckets().build()); return groupBuilder.build(); } private static BucketsBuilder createBuckets() { List actionList = new ArrayList<>(); actionList.add(new ActionBuilder() .setOrder(0) .setAction(new PopVlanActionCaseBuilder() .setPopVlanAction(new PopVlanActionBuilder().build()) .build()).build()); BucketBuilder bucketBuilder = new BucketBuilder(); bucketBuilder.setBucketId(new BucketId(12L)); bucketBuilder.setAction(actionList); List bucketList = new ArrayList<>(); bucketList.add(bucketBuilder.build()); actionList = new ArrayList<>(); SetFieldCaseBuilder setFieldCaseBuilder = new SetFieldCaseBuilder(); setFieldCaseBuilder.setSetField(new SetFieldBuilder() .setLayer3Match(new Ipv4MatchBuilder() .setIpv4Source(new Ipv4Prefix("10.0.1.0/32")) .build()) .build()); actionList.add(new ActionBuilder() .setAction(setFieldCaseBuilder.build()) .setOrder(0) .build()); setFieldCaseBuilder = new SetFieldCaseBuilder(); setFieldCaseBuilder.setSetField(new SetFieldBuilder() .setLayer3Match(new Ipv4MatchBuilder() .setIpv4Destination(new Ipv4Prefix("10.0.10.0/32")) .build()) .build()); actionList.add(new ActionBuilder() .setAction(setFieldCaseBuilder.build()) .setOrder(0) .build()); bucketBuilder = new BucketBuilder(); bucketBuilder.setBucketId(new BucketId(13L)); bucketBuilder.setAction(actionList); bucketList.add(bucketBuilder.build()); BucketsBuilder bucketsBuilder = new BucketsBuilder(); bucketsBuilder.setBucket(bucketList); return bucketsBuilder; } private static InstructionsBuilder createGroupInstructions(long groupId) { ActionBuilder actionBuilder = new ActionBuilder(); GroupActionBuilder groupActionBuilder = new GroupActionBuilder(); groupActionBuilder.setGroupId(groupId); actionBuilder.setAction(new GroupActionCaseBuilder().setGroupAction(groupActionBuilder.build()).build()); actionBuilder.setOrder(1); actionBuilder.setKey(new ActionKey(0)); List actionList = new ArrayList<>(); actionList.add(actionBuilder.build()); ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder(); applyActionsBuilder.setAction(actionList); InstructionBuilder instructionBuilder = new InstructionBuilder(); instructionBuilder.setInstruction(new ApplyActionsCaseBuilder() .setApplyActions(applyActionsBuilder.build()).build()); instructionBuilder.setOrder(0); instructionBuilder.setKey(new InstructionKey(0)); InstructionsBuilder instructionsBuilder = new InstructionsBuilder(); List instructions = new ArrayList<>(); instructions.add(instructionBuilder.build()); instructionsBuilder.setInstruction(instructions); return instructionsBuilder; } }