From 981ef67ba1ee255891c09e03c8e20f6aef319653 Mon Sep 17 00:00:00 2001 From: Tomas Cechvala Date: Mon, 5 Dec 2016 15:37:15 +0100 Subject: [PATCH] Introducing RPCs for remote calls to VPP Allowing other plugins to interact with VPP by using VPP renderer. RPCs allow creating bridge domains, interfaces and assigning bridge domains to interfaces. Change-Id: Iddcf4b127ebe5757405d6041746a9559365156ee Signed-off-by: Tomas Cechvala --- .../vpp/mapper/processors/NetworkAware.java | 4 +- .../vpp/mapper/processors/PortHandler.java | 10 +- .../mapper/processors/NetworkAwareTest.java | 2 +- .../mapper/processors/PortHandlerTest.java | 2 +- .../impl/GbpVppProviderInstance.java | 50 ++- .../config/vpp_provider/impl/VppRenderer.java | 12 +- .../vpp/external/VppRpcServiceImpl.java | 315 ++++++++++++++++++ .../renderer/vpp/iface/InterfaceManager.java | 135 +++++--- .../vpp/policy/BridgeDomainManagerImpl.java | 25 +- .../vpp/policy/ForwardingManager.java | 4 +- .../renderer/vpp/util/VppIidFactory.java | 9 + .../opendaylight/blueprint/vpp-renderer.xml | 3 + renderers/vpp/src/main/yang/vpp-adapter.yang | 112 +++++++ renderers/vpp/src/main/yang/vpp-renderer.yang | 161 +++++---- .../vpp/iface/InterfaceManagerTest.java | 2 +- .../policy/VppRendererPolicyManagerTest.java | 4 +- 16 files changed, 694 insertions(+), 156 deletions(-) create mode 100644 renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/external/VppRpcServiceImpl.java create mode 100644 renderers/vpp/src/main/yang/vpp-adapter.yang diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAware.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAware.java index 265c8e90a..577e36eaf 100644 --- a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAware.java +++ b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAware.java @@ -23,8 +23,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_render import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpBridgeDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpBridgeDomainBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpBridgeDomainKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.gbp.bridge.domain.PhysicalLocationRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.gbp.bridge.domain.PhysicalLocationRefBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRefBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeFlat; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVlan; diff --git a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java index 434da171c..fb7fdfa26 100644 --- a/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java +++ b/neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java @@ -32,11 +32,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_render import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.LoopbackCase; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.LoopbackCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.TapCase; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.TapCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.binding.attributes.VifDetails; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers; diff --git a/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAwareTest.java b/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAwareTest.java index 2a1e84bae..5b45f2162 100644 --- a/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAwareTest.java +++ b/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/NetworkAwareTest.java @@ -29,7 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types. import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.FlatNetwork; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VlanNetwork; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpBridgeDomain; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.gbp.bridge.domain.PhysicalLocationRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeFlat; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVlan; diff --git a/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandlerTest.java b/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandlerTest.java index fd9d3cf8d..7e2eadf2c 100644 --- a/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandlerTest.java +++ b/neutron-vpp-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandlerTest.java @@ -36,7 +36,7 @@ import org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.SocketInfo; import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; diff --git a/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/GbpVppProviderInstance.java b/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/GbpVppProviderInstance.java index 566b5e9e3..1e548e1b2 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/GbpVppProviderInstance.java +++ b/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/GbpVppProviderInstance.java @@ -8,20 +8,33 @@ package org.opendaylight.controller.config.yang.config.vpp_provider.impl; +import java.util.concurrent.Future; + import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; + import org.opendaylight.controller.config.yang.config.groupbasedpolicy.GroupbasedpolicyInstance; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.groupbasedpolicy.renderer.vpp.adapter.VppRpcServiceImpl; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration; import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.AddInterfaceToBridgeDomainInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.CreateInterfaceOnNodeInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.CreateVirtualBridgeDomainOnNodesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DelInterfaceFromBridgeDomainInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DeleteInterfaceInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DeleteVirtualBridgeDomainOnNodesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.ExpandVirtualBridgeDomainOnNodesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.VppAdapterService; +import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class GbpVppProviderInstance implements ClusterSingletonService, AutoCloseable { +public class GbpVppProviderInstance implements ClusterSingletonService, VppAdapterService, AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(GbpVppProviderInstance.class); @@ -81,4 +94,39 @@ public class GbpVppProviderInstance implements ClusterSingletonService, AutoClos public ServiceGroupIdentifier getIdentifier() { return IDENTIFIER; } + + @Override + public Future> deleteVirtualBridgeDomainOnNodes(DeleteVirtualBridgeDomainOnNodesInput input) { + return renderer.getVppRpcServiceImpl().deleteVirtualBridgeDomain(input); + } + + @Override + public Future> createVirtualBridgeDomainOnNodes(CreateVirtualBridgeDomainOnNodesInput input) { + return renderer.getVppRpcServiceImpl().createVirtualBridgeDomain(input); + } + + @Override + public Future> createInterfaceOnNode(CreateInterfaceOnNodeInput input) { + return renderer.getVppRpcServiceImpl().createInterfaceOnNode(input); + } + + @Override + public Future> deleteInterface(DeleteInterfaceInput input) { + return renderer.getVppRpcServiceImpl().deleteInterfaceOnNode(input); + } + + @Override + public Future> addInterfaceToBridgeDomain(AddInterfaceToBridgeDomainInput input) { + return renderer.getVppRpcServiceImpl().addInterfaceToBridgeDomain(input); + } + + @Override + public Future> delInterfaceFromBridgeDomain(DelInterfaceFromBridgeDomainInput input) { + return renderer.getVppRpcServiceImpl().delInterfaceFromBridgeDomain(input); + } + + @Override + public Future> expandVirtualBridgeDomainOnNodes(ExpandVirtualBridgeDomainOnNodesInput input) { + return renderer.getVppRpcServiceImpl().expandVirtualBridgeDomainOnNode(input); + } } diff --git a/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java b/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java index 72b896f7c..3e7a9b5bb 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java +++ b/renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java @@ -19,6 +19,8 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; +import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.adapter.VppRpcServiceImpl; import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.RendererPolicyListener; import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppEndpointListener; @@ -81,6 +83,7 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider { private VppNodeListener vppNodeListener; private VppEndpointListener vppEndpointListener; private RendererPolicyListener rendererPolicyListener; + private VppRpcServiceImpl vppRpcServiceImpl; public VppRenderer(DataBroker dataBroker, BindingAwareBroker bindingAwareBroker) { this.dataBroker = Preconditions.checkNotNull(dataBroker); @@ -118,14 +121,15 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider { context.getSubscriber(), context.getSubscriberMethod(), exception)); interfaceManager = new InterfaceManager(mountDataProvider, dataBroker, NETCONF_WORKER); dtoEventBus.register(interfaceManager); - ForwardingManager fwManager = new ForwardingManager(interfaceManager, new BridgeDomainManagerImpl(dataBroker), dataBroker); + BridgeDomainManager bdManager = new BridgeDomainManagerImpl(dataBroker); + ForwardingManager fwManager = new ForwardingManager(interfaceManager, bdManager, dataBroker); vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, dataBroker); dtoEventBus.register(vppRendererPolicyManager); vppNodeListener = new VppNodeListener(dataBroker, vppNodeManager, dtoEventBus); vppEndpointListener = new VppEndpointListener(dataBroker, dtoEventBus); rendererPolicyListener = new RendererPolicyListener(dataBroker, dtoEventBus); - + vppRpcServiceImpl = new VppRpcServiceImpl(dataBroker, mountDataProvider, bdManager, interfaceManager); registerToRendererManager(); } @@ -175,4 +179,8 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider { } }); } + + VppRpcServiceImpl getVppRpcServiceImpl() { + return vppRpcServiceImpl; + } } diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/external/VppRpcServiceImpl.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/external/VppRpcServiceImpl.java new file mode 100644 index 000000000..65448169c --- /dev/null +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/external/VppRpcServiceImpl.java @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. 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.groupbasedpolicy.renderer.vpp.adapter; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand; +import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.TapPortCommand; +import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand; +import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand.VhostUserCommandBuilder; +import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager; +import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations; +import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider; +import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.AddInterfaceToBridgeDomainInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.CreateInterfaceOnNodeInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.CreateVirtualBridgeDomainOnNodesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DelInterfaceFromBridgeDomainInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DeleteInterfaceInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DeleteVirtualBridgeDomainOnNodesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.ExpandVirtualBridgeDomainOnNodesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.bridge.domain.attributes.tunnel.type.Vlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.bridge.domain.attributes.tunnel.type.Vxlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes.InterfaceTypeChoice; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUserRole; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanVni; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyTypesVbridgeAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vlan.rev160429.TunnelTypeVlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vlan.rev160429.network.topology.topology.tunnel.parameters.VlanNetworkParameters; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev160429.TunnelTypeVxlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev160429.network.topology.topology.tunnel.parameters.VxlanTunnelParameters; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +public class VppRpcServiceImpl { + + private static final Logger LOG = LoggerFactory.getLogger(VppRpcServiceImpl.class); + + private final DataBroker dataBroker; + private final BridgeDomainManager bridgeDomainManager; + private final InterfaceManager interfaceManager; + private final MountedDataBrokerProvider mountDataProvider; + + public VppRpcServiceImpl(@Nonnull DataBroker dataBroker, @Nonnull MountedDataBrokerProvider mountDataProvider, + BridgeDomainManager bridgeDomainManager, InterfaceManager interfaceManager) { + this.dataBroker = dataBroker; + this.bridgeDomainManager = bridgeDomainManager; + this.interfaceManager = interfaceManager; + this.mountDataProvider = mountDataProvider; + } + + public Future> createVirtualBridgeDomain(CreateVirtualBridgeDomainOnNodesInput input) { + if (input.getTunnelType() == null) { + return Futures.immediateFuture(RpcResultBuilder.failed() + .withError(ErrorType.RPC, + "Failed to create bridge domain" + input.getId() + "." + "Tunnel type not specified") + .build()); + } + List> futures = new ArrayList<>(); + List nodeIds = input.getPhysicalLocationRef() + .stream() + .map(locationRef -> locationRef.getNodeId()) + .collect(Collectors.toList()); + if (input.getTunnelType() instanceof Vxlan) { + Vxlan tunnelType = (Vxlan) input.getTunnelType(); + VxlanVni vxlanVni = new VxlanVni(tunnelType.getVni().getValue()); + nodeIds.forEach(nodeId -> { + futures.add(bridgeDomainManager.createVxlanBridgeDomainOnVppNode(input.getId(), vxlanVni, nodeId)); + }); + } else if (input.getTunnelType() instanceof Vlan) { + Vlan vlan = (Vlan) input.getTunnelType(); + VlanId vlanId = new VlanId(vlan.getVlanId().getValue()); + nodeIds.forEach(nodeId -> { + futures.add(bridgeDomainManager.createVlanBridgeDomainOnVppNode(input.getId(), vlanId, nodeId)); + }); + } + return Futures.transform(Futures.allAsList(futures), voidsToRpcResult()); + } + + public Future> deleteVirtualBridgeDomain(DeleteVirtualBridgeDomainOnNodesInput input) { + List> futures = new ArrayList<>(); + input.getBridgeDomainNode().forEach(nodeId -> { + futures.add(bridgeDomainManager.removeBridgeDomainFromVppNode(input.getBridgeDomainId(), nodeId)); + }); + return Futures.transform(Futures.allAsList(futures), voidsToRpcResult()); + } + + public ListenableFuture> expandVirtualBridgeDomainOnNode(ExpandVirtualBridgeDomainOnNodesInput input) { + List> futures = new ArrayList<>(); + ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction(); + InstanceIdentifier topologyIid = VppIidFactory.getTopologyIid(new TopologyKey(new TopologyId( + input.getBridgeDomainId()))); + return Futures.transform(rTx.read(LogicalDatastoreType.OPERATIONAL, topologyIid), + new AsyncFunction, RpcResult>() { + + @Override + public ListenableFuture> apply(Optional optTopology) throws Exception { + if (!optTopology.isPresent()) { + + return Futures.immediateFuture(RpcResultBuilder.failed() + .withError( + ErrorType.RPC, + "Failed to expand bridge domain. Bridge domain " + input.getBridgeDomainId() + + " does not exist.") + .build()); + } + TopologyTypes topologyTypes = optTopology.get().getTopologyTypes(); + if (topologyTypes == null + || topologyTypes.getAugmentation(TopologyTypesVbridgeAugment.class) == null + || optTopology.get().getAugmentation(TopologyVbridgeAugment.class) == null) { + return Futures.immediateFuture(RpcResultBuilder.failed() + .withError( + ErrorType.RPC, + "Failed to expand bridge domain. Topology " + input.getBridgeDomainId() + + " is not bridge domain type.") + .build()); + } + TopologyVbridgeAugment vBridge = optTopology.get() + .getAugmentation(TopologyVbridgeAugment.class); + if (vBridge.getTunnelParameters() instanceof TunnelTypeVxlan) { + VxlanTunnelParameters vxlanTunnelParams = (VxlanTunnelParameters) vBridge.getTunnelParameters(); + VxlanVni vni = vxlanTunnelParams.getVni(); + input.getBridgeDomainNode().forEach( + nodeId -> { + futures.add(bridgeDomainManager.createVxlanBridgeDomainOnVppNode( + input.getBridgeDomainId(), vni, nodeId)); + }); + } else if (vBridge.getTunnelParameters() instanceof TunnelTypeVlan) { + VlanNetworkParameters vlanTunnelParams = (VlanNetworkParameters) vBridge.getTunnelParameters(); + VlanId vlanId = vlanTunnelParams.getVlanId(); + input.getBridgeDomainNode().forEach( + nodeId -> { + futures.add(bridgeDomainManager.createVlanBridgeDomainOnVppNode( + input.getBridgeDomainId(), vlanId, nodeId)); + }); + } + return Futures.transform(Futures.allAsList(futures), voidsToRpcResult()); + } + }); + } + + public ListenableFuture> createInterfaceOnNode(CreateInterfaceOnNodeInput input) { + InterfaceTypeChoice interfaceType = input.getInterfaceTypeChoice(); + ConfigCommand ifaceCommand = null; + if (interfaceType instanceof VhostUserCase) { + VhostUserCommandBuilder vhostBuilder = VhostUserCommand.builder(); + vhostBuilder.setName(input.getVppInterfaceName()); + VhostUserCase vhostCase = (VhostUserCase) input.getInterfaceTypeChoice(); + vhostBuilder.setSocket(vhostCase.getSocket()); + vhostBuilder.setRole(VhostUserRole.Client); + vhostBuilder.setDescription(input.getDescription()); + vhostBuilder.setOperation(Operations.PUT); + ifaceCommand = vhostBuilder.build(); + } + if (interfaceType instanceof TapCase) { + TapPortCommand.TapPortCommandBuilder tapBuilder = TapPortCommand.builder(); + TapCase tapIface = (TapCase) input.getInterfaceTypeChoice(); + tapBuilder.setTapName(tapIface.getName()); + tapBuilder.setPhysAddress(tapIface.getPhysicalAddress()); + tapBuilder.setInterfaceName(input.getVppInterfaceName()); + tapBuilder.setDescription(input.getDescription()); + tapBuilder.setOperation(Operations.PUT); + ifaceCommand = tapBuilder.build(); + } + Optional optDataBroker = mountDataProvider.getDataBrokerForMountPoint(input.getVppNodePath()); + if (!optDataBroker.isPresent()) { + return Futures.immediateFuture(RpcResultBuilder.failed() + .withError(ErrorType.RPC, "Cannot find data broker for mount point " + input.getVppNodePath()) + .build()); + } + return Futures.transform(interfaceManager.createInterfaceOnVpp(ifaceCommand, optDataBroker.get()), + voidToRpcResult()); + } + + public ListenableFuture> deleteInterfaceOnNode(DeleteInterfaceInput input) { + return Futures.transform(readInterface(input.getVppNodePath(), input.getVppInterfaceName()), + new AsyncFunction, RpcResult>() { + + @Override + public ListenableFuture> apply(Optional optIface) throws Exception { + InterfaceKey iKey = new InterfaceKey(input.getVppInterfaceName()); + if (!optIface.isPresent()) { + return Futures.immediateFuture(RpcResultBuilder.failed() + .withError( + ErrorType.RPC, + "Cannot delete interface " + iKey + " on node " + input.getVppNodePath() + + ". Not found or already deleted.") + .build()); + } + Optional dataBroker = mountDataProvider.getDataBrokerForMountPoint(input.getVppNodePath()); + WriteTransaction wTx = dataBroker.get().newWriteOnlyTransaction(); + wTx.delete(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getInterfaceIID(iKey)); + return Futures.transform(wTx.submit(), voidToRpcResult()); + } + }); + } + + public ListenableFuture> addInterfaceToBridgeDomain(AddInterfaceToBridgeDomainInput input) { + return Futures.transform(readInterface(input.getVppNodePath(), input.getVppInterfaceName()), + new AsyncFunction, RpcResult>() { + + @Override + public ListenableFuture> apply(Optional optIface) throws Exception { + InterfaceKey iKey = new InterfaceKey(input.getVppInterfaceName()); + if (!optIface.isPresent()) { + return Futures.immediateFuture(RpcResultBuilder.failed() + .withError( + ErrorType.RPC, + "Cannot add interface " + iKey + " to bridge domain on node " + + input.getVppNodePath() + ". Not found or deleted.") + .build()); + } + Optional dataBroker = mountDataProvider.getDataBrokerForMountPoint(input.getVppNodePath()); + return Futures.transform(interfaceManager.configureInterface(dataBroker.get(), iKey, + input.getBridgeDomainId(), null), voidToRpcResult()); + } + }); + } + + public ListenableFuture> delInterfaceFromBridgeDomain(DelInterfaceFromBridgeDomainInput input) { + return Futures.transform(readInterface(input.getVppNodePath(), input.getVppInterfaceName()), + new AsyncFunction, RpcResult>() { + + @Override + public ListenableFuture> apply(Optional optIface) throws Exception { + if (!optIface.isPresent()) { + return Futures.immediateFuture(RpcResultBuilder.failed() + .withError( + ErrorType.RPC, + "Cannot remove interface " + input.getVppInterfaceName() + + " from bridge domain on node " + input.getVppNodePath() + + ". Not found or deleted.") + .build()); + } + Optional dataBroker = mountDataProvider.getDataBrokerForMountPoint(input.getVppNodePath()); + return Futures.transform(interfaceManager.removeInterfaceFromBridgeDomain(dataBroker.get(), + optIface.get().getKey()), voidToRpcResult()); + } + }); + } + + private CheckedFuture, ReadFailedException> readInterface(InstanceIdentifier nodeIid, + String interfaceName) { + Optional optDataBroker = mountDataProvider.getDataBrokerForMountPoint(nodeIid); + if (!optDataBroker.isPresent()) { + LOG.error("Cannot find data broker for node {}", nodeIid); + return Futures.immediateCheckedFuture(Optional.absent()); + } + ReadOnlyTransaction rwTx = optDataBroker.get().newReadOnlyTransaction(); + InterfaceKey iKey = new InterfaceKey(interfaceName); + InstanceIdentifier interfaceIID = VppIidFactory.getInterfaceIID(iKey); + CheckedFuture, ReadFailedException> readInterface = rwTx.read( + LogicalDatastoreType.CONFIGURATION, interfaceIID); + rwTx.close(); + return readInterface; + } + + private AsyncFunction> voidToRpcResult() { + return new AsyncFunction>() { + + @Override + public ListenableFuture> apply(Void input) throws Exception { + return Futures.immediateFuture(RpcResultBuilder.success().build()); + } + }; + } + + private AsyncFunction, RpcResult> voidsToRpcResult() { + return new AsyncFunction, RpcResult>() { + + @Override + public ListenableFuture> apply(List input) throws Exception { + return Futures.immediateFuture(RpcResultBuilder.success().build()); + } + }; + } +} diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java index d32222498..256216441 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java @@ -8,18 +8,12 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.iface; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.eventbus.Subscribe; -import com.google.common.util.concurrent.AsyncFunction; -import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -33,17 +27,19 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.event.NodeOperEvent; import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider; +import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory; import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes.InterfaceTypeChoice; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint.InterfaceTypeChoice; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.LoopbackCase; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.TapCase; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUserRole; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2; @@ -56,6 +52,15 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.eventbus.Subscribe; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + public class InterfaceManager implements AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class); @@ -115,23 +120,24 @@ public class InterfaceManager implements AutoCloseable { return Futures.immediateFuture(null); } DataBroker vppDataBroker = potentialVppDataProvider.get(); - return createInterfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid); + return Futures.transform(createInterfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker), + new AsyncFunction() { + + @Override + public ListenableFuture apply(@Nonnull Void input) { + LOG.debug("Create interface on VPP command was successful. VPP: {} Command: {}", vppNodeIid, + ifaceWithoutBdCommand); + return vppEndpointLocationProvider.createLocationForVppEndpoint(vppEndpoint); + } + }, netconfWorker); } - private ListenableFuture createInterfaceOnVpp(ConfigCommand createIfaceWithoutBdCommand, DataBroker vppDataBroker, - VppEndpoint vppEndpoint, InstanceIdentifier vppNodeIid) { + public ListenableFuture createInterfaceOnVpp(ConfigCommand createIfaceWithoutBdCommand, + DataBroker vppDataBroker) { final ReadWriteTransaction rwTx = vppDataBroker.newReadWriteTransaction(); createIfaceWithoutBdCommand.execute(rwTx); LOG.trace("Creating Interface on VPP: {}", createIfaceWithoutBdCommand); - return Futures.transform(rwTx.submit(), new AsyncFunction() { - - @Override - public ListenableFuture apply(@Nonnull Void input) { - LOG.debug("Create interface on VPP command was successful. VPP: {} Command: {}", vppNodeIid, - createIfaceWithoutBdCommand); - return vppEndpointLocationProvider.createLocationForVppEndpoint(vppEndpoint); - } - }, netconfWorker); + return rwTx.submit(); } private ListenableFuture vppEndpointUpdated(@Nonnull final VppEndpoint oldVppEndpoint, @@ -174,24 +180,23 @@ public class InterfaceManager implements AutoCloseable { return Futures.immediateFuture(null); } DataBroker vppDataBroker = potentialVppDataProvider.get(); - return deleteIfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid); + return Futures.transform(deleteIfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker), + new AsyncFunction() { + + @Override + public ListenableFuture apply(Void input) { + LOG.debug("Delete interface on VPP command was successful: VPP: {} Command: {}", vppNodeIid, + ifaceWithoutBdCommand); + return vppEndpointLocationProvider.deleteLocationForVppEndpoint(vppEndpoint); + } + }, netconfWorker); } - private ListenableFuture deleteIfaceOnVpp(ConfigCommand deleteIfaceWithoutBdCommand, - DataBroker vppDataBroker, VppEndpoint vppEndpoint, InstanceIdentifier vppNodeIid) { + public ListenableFuture deleteIfaceOnVpp(ConfigCommand deleteIfaceWithoutBdCommand, DataBroker vppDataBroker) { ReadWriteTransaction rwTx = vppDataBroker.newReadWriteTransaction(); deleteIfaceWithoutBdCommand.execute(rwTx); LOG.trace("Deleting Interface on VPP: {}", deleteIfaceWithoutBdCommand); - - return Futures.transform(rwTx.submit(), new AsyncFunction() { - - @Override - public ListenableFuture apply(Void input) { - LOG.debug("Delete interface on VPP command was successful: VPP: {} Command: {}", vppNodeIid, - deleteIfaceWithoutBdCommand); - return vppEndpointLocationProvider.deleteLocationForVppEndpoint(vppEndpoint); - } - }, netconfWorker); + return rwTx.submit(); } @Subscribe @@ -216,7 +221,7 @@ public class InterfaceManager implements AutoCloseable { } } - private static Optional createInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp, + public static Optional createInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp, @Nonnull Operations operations) { if (!hasNodeAndInterface(vppEp)) { LOG.debug("Interface command is not created for {}", vppEp); @@ -318,7 +323,6 @@ public class InterfaceManager implements AutoCloseable { new Exception("Cannot resolve interface instance-identifier for interface path" + interfacePath)); } InstanceIdentifier interfaceIid = optInterfaceIid.get(); - Optional potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid); if (!potentialVppDataProvider.isPresent()) { return Futures.immediateFailedFuture(new Exception("Cannot get data broker for mount point " + vppNodeIid)); @@ -335,7 +339,6 @@ public class InterfaceManager implements AutoCloseable { return Futures.immediateFailedFuture(new Exception("Interface " + interfaceIid.firstKeyOf(Interface.class) + " does not exist on node " + vppNodeIid)); } - String existingBridgeDomain = resolveBridgeDomain(optIface.get()); if (bridgeDomainName.equals(existingBridgeDomain)) { LOG.debug("Bridge domain {} already exists on interface {}", bridgeDomainName, interfacePath); @@ -349,18 +352,9 @@ public class InterfaceManager implements AutoCloseable { } return Futures.immediateFuture(null); } - InstanceIdentifier l2Iid = - interfaceIid.builder().augmentation(VppInterfaceAugmentation.class).child(L2.class).build(); - final ReadWriteTransaction rwTxRead = mountpoint.newReadWriteTransaction(); - Optional optL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l2Iid, rwTxRead); - L2Builder l2Builder = (optL2.isPresent()) ? new L2Builder(optL2.get()) : new L2Builder(); - L2 l2 = l2Builder.setInterconnection(new BridgeBasedBuilder() - .setBridgeDomain(bridgeDomainName) - .setBridgedVirtualInterface(enableBvi) - .build()).build(); - final ReadWriteTransaction rwTxPut = prepareTransactionAndPutData(mountpoint, l2, l2Iid); - LOG.debug("Adding bridge domain {} to interface {}", bridgeDomainName, interfacePath); - return Futures.transform(rwTxPut.submit(), new AsyncFunction() { + return Futures.transform( + configureInterface(mountpoint, optIface.get().getKey(), bridgeDomainName, enableBvi), + new AsyncFunction() { @Override public ListenableFuture apply(@Nonnull Void input) { @@ -376,6 +370,39 @@ public class InterfaceManager implements AutoCloseable { }, netconfWorker); } + public ListenableFuture configureInterface(DataBroker mountPoint, InterfaceKey ifaceKey, @Nullable String bridgeDomainName, @Nullable Boolean enableBvi) { + L2Builder l2Builder = readL2ForInterface(mountPoint, ifaceKey); + L2 l2 = l2Builder.setInterconnection(new BridgeBasedBuilder() + .setBridgeDomain(bridgeDomainName) + .setBridgedVirtualInterface(enableBvi) + .build()).build(); + final ReadWriteTransaction rwTxPut = prepareTransactionAndPutData(mountPoint, l2, VppIidFactory.getL2ForInterfaceIid(ifaceKey)); + LOG.debug("Adding bridge domain {} to interface {}", bridgeDomainName, VppIidFactory.getInterfaceIID(ifaceKey)); + return rwTxPut.submit(); + } + + public ListenableFuture removeInterfaceFromBridgeDomain(DataBroker mountPoint, InterfaceKey ifaceKey) { + L2Builder l2Builder = readL2ForInterface(mountPoint, ifaceKey); + if (l2Builder.getInterconnection() == null || !(l2Builder.getInterconnection() instanceof BridgeBased)) { + LOG.warn("Interface already not in bridge domain {} ", ifaceKey); + return Futures.immediateFuture(null); + } + BridgeBased bridgeBased = new BridgeBasedBuilder((BridgeBased) l2Builder.getInterconnection()).setBridgeDomain( + null).build(); + L2 l2 = l2Builder.setInterconnection(bridgeBased).build(); + final ReadWriteTransaction rwTxPut = prepareTransactionAndPutData(mountPoint, l2, + VppIidFactory.getL2ForInterfaceIid(ifaceKey)); + LOG.debug("Removing bridge domain from interface {}", VppIidFactory.getInterfaceIID(ifaceKey)); + return rwTxPut.submit(); + } + + private L2Builder readL2ForInterface(DataBroker mountpoint, InterfaceKey ifaceKey) { + InstanceIdentifier l2Iid = VppIidFactory.getL2ForInterfaceIid(ifaceKey); + final ReadWriteTransaction rwTxRead = mountpoint.newReadWriteTransaction(); + Optional optL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l2Iid, rwTxRead); + return (optL2.isPresent()) ? new L2Builder(optL2.get()) : new L2Builder(); + } + /** * Removes bridge domain (if exist) from an interface (if exist).
* {@link VppEndpointLocationProvider#VPP_ENDPOINT_LOCATION_PROVIDER} will update endpoint diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImpl.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImpl.java index c1546d56e..6b695324b 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImpl.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImpl.java @@ -8,20 +8,14 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.policy; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.AsyncFunction; -import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.SettableFuture; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + 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; @@ -35,9 +29,9 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpBridgeDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpBridgeDomainKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.gbp.bridge.domain.PhysicalLocationRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanVni; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomain; @@ -75,6 +69,15 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; + public class BridgeDomainManagerImpl implements BridgeDomainManager { private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainManagerImpl.class); diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java index 5823d5bc4..9e5e70c9b 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java @@ -47,8 +47,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_render import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpBridgeDomainKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint.InterfaceTypeChoice; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.LoopbackCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes.InterfaceTypeChoice; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanVni; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java index 366d3c5c9..e22dd8207 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java @@ -18,7 +18,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppState; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.BridgeDomains; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomainKey; @@ -35,6 +37,13 @@ public class VppIidFactory { return InstanceIdentifier.create(Interfaces.class).child(Interface.class, interfaceKey); } + public static InstanceIdentifier getL2ForInterfaceIid(InterfaceKey interfaceKey) { + return getInterfaceIID(interfaceKey).builder() + .augmentation(VppInterfaceAugmentation.class) + .child(L2.class) + .build(); + } + public static InstanceIdentifier getRendererIID(RendererKey rendererKey) { return InstanceIdentifier.create(Renderers.class).child(Renderer.class, rendererKey); } diff --git a/renderers/vpp/src/main/resources/org/opendaylight/blueprint/vpp-renderer.xml b/renderers/vpp/src/main/resources/org/opendaylight/blueprint/vpp-renderer.xml index ba47a38e5..62a8dbfbd 100644 --- a/renderers/vpp/src/main/resources/org/opendaylight/blueprint/vpp-renderer.xml +++ b/renderers/vpp/src/main/resources/org/opendaylight/blueprint/vpp-renderer.xml @@ -13,4 +13,7 @@ + + + \ No newline at end of file diff --git a/renderers/vpp/src/main/yang/vpp-adapter.yang b/renderers/vpp/src/main/yang/vpp-adapter.yang new file mode 100644 index 000000000..9d8d16925 --- /dev/null +++ b/renderers/vpp/src/main/yang/vpp-adapter.yang @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. 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 + */ + +module vpp-adapter { + yang-version 1; + + namespace "urn:opendaylight:groupbasedpolicy:vpp_adapter"; + prefix "vpp-adapter"; + + import vpp-renderer { prefix "vpp-renderer"; } + import network-topology { prefix nt; revision-date 2013-10-21; } + import opendaylight-l2-types { prefix l2-types; revision-date "2013-08-27"; } + import ietf-yang-types { prefix yang-types; revision-date "2013-07-15"; } + import ietf-inet-types { prefix "inet-types"; } + + description + "This module allows external plugins to use VPP renderer by calling defined RPCs."; + + revision "2016-12-01" { + description + "Initial revision."; + } + + typedef vxlan-vni-type { + type uint32 { + range "1 .. 16777214"; + } + } + + grouping bridge-domain-attributes { + uses vpp-renderer:bridge-domain-base-attributes; + leaf unknown-unicast-flood { + type boolean; + default "False"; + } + choice tunnel-type { + case vxlan { + leaf vni { + type vxlan-vni-type; + } + } + case vlan { + leaf vlan-id { + type l2-types:vlan-id; + } + } + } + } + + grouping bridge-domain-nodes { + uses bridge-domain-id; + leaf-list bridge-domain-node { + min-elements 1; + type nt:node-id; + } + } + + grouping bridge-domain-id { + leaf bridge-domain-id { + mandatory true; + type string; + } + } + + rpc create-virtual-bridge-domain-on-nodes { + input { + uses bridge-domain-attributes; + } + } + + rpc expand-virtual-bridge-domain-on-nodes { + input { + uses bridge-domain-nodes; + } + } + + rpc delete-virtual-bridge-domain-on-nodes { + input { + uses bridge-domain-nodes; + } + } + + rpc create-interface-on-node { + input { + uses vpp-renderer:interface-attributes; + } + } + + rpc delete-interface { + input { + uses vpp-renderer:interface-location; + } + } + + rpc add-interface-to-bridge-domain { + input { + uses vpp-renderer:interface-location; + uses bridge-domain-id; + } + } + + rpc del-interface-from-bridge-domain { + input { + uses vpp-renderer:interface-location; + } + } +} diff --git a/renderers/vpp/src/main/yang/vpp-renderer.yang b/renderers/vpp/src/main/yang/vpp-renderer.yang index 25b3f835e..116adc755 100644 --- a/renderers/vpp/src/main/yang/vpp-renderer.yang +++ b/renderers/vpp/src/main/yang/vpp-renderer.yang @@ -47,79 +47,106 @@ module vpp-renderer { } } - container config { - list vpp-endpoint { - description "Renderer creates/removes interface on VPP node based on given parameters."; - - key "context-type context-id address-type address"; - uses base-ep:address-endpoint-key; - - leaf vpp-node-path { - description "Path to a node representing mount-point to VPP instance."; - mandatory true; - type instance-identifier; - } - leaf vpp-interface-name { - description "Name of interface for the endpoint on VPP"; - mandatory true; - type string; + grouping bridge-domain-base-attributes { + leaf id { + description "Same as in VBD."; + type string; + } + leaf description { + type string; + } + list physical-location-ref { + description + "Refers to physical interfaces on vpp nodes through which external + nodes belonging to the same bridge-domain can be reached."; + key "node-id"; + leaf node-id { + description "Refers to a VPP node."; + type nt:node-id; } - leaf description { - description "Additional description of the vpp-endpoint"; + leaf-list interface { + description "Physical interface on the VPP node."; type string; } - choice interface-type-choice { - case vhost-user-case { - leaf socket { - description "Identifier of a vhost user"; - type string { - length 1..255; - } + } + } + + grouping interface-attributes { + uses vpp-renderer:interface-location; + leaf description { + description "Additional description of the vpp-endpoint"; + type string; + } + choice interface-type-choice { + mandatory true; + case vhost-user-case { + leaf socket { + description "Identifier of a vhost user"; + type string { + length 1..255; } } - case tap-case { - leaf name { - description "Identifier of a tap port"; - mandatory true; - type string { - length 1..255; - } - } - leaf physical-address { - description "MAC address of a tap port"; - type yang-types:phys-address; + } + case tap-case { + leaf name { + description "Identifier of a tap port"; + mandatory true; + type string { + length 1..255; } } - case loopback-case { - leaf phys-address { - description "MAC address of a loopback interface"; - type yang-types:phys-address; - } - leaf ip-address { - description "Ip address of a loopback interface"; - type inet-types:ip-address; - } - leaf ip-prefix { - description "Ip address prefix of a loopback interface"; - type inet-types:ip-prefix; - } - leaf bvi { - description "Enable/disable BVI for loopback interface"; - type boolean; - } + leaf physical-address { + description "MAC address of a tap port"; + type yang-types:phys-address; + } + } + case loopback-case { + leaf phys-address { + description "MAC address of a loopback interface"; + type yang-types:phys-address; + } + leaf ip-address { + description "Ip address of a loopback interface"; + type inet-types:ip-address; + } + leaf ip-prefix { + description "Ip address prefix of a loopback interface"; + type inet-types:ip-prefix; + } + leaf bvi { + description "Enable/disable BVI for loopback interface"; + type boolean; } } } + } + + grouping interface-location { + leaf vpp-node-path { + description "Path to a node representing mount-point to VPP instance."; + mandatory true; + type instance-identifier; + } + leaf vpp-interface-name { + description "Name of interface for the endpoint on VPP"; + mandatory true; + type string; + } + } + + container config { + list vpp-endpoint { + description "Renderer creates/removes interface on VPP node based on given parameters."; + + key "context-type context-id address-type address"; + uses base-ep:address-endpoint-key; + + uses interface-attributes; + } list gbp-bridge-domain { key "id"; - leaf id { - description "Same as in VBD."; - type string; - } - leaf description { - type string; - } + uses bridge-domain-base-attributes; leaf type { mandatory true; type network-type; @@ -128,20 +155,6 @@ module vpp-renderer { when "type = 'vlan-network'"; type l2-types:vlan-id; } - list physical-location-ref { - description - "Refers to physical interfaces on vpp nodes through which external - nodes belonging to the same bridge-domain can be reached."; - key "node-id"; - leaf node-id { - description "Refers to a VPP node."; - type nt:node-id; - } - leaf-list interface { - description "Physical interface on the VPP node."; - type string; - } - } } } } diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManagerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManagerTest.java index b3839f02d..f9f6b77eb 100644 --- a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManagerTest.java +++ b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManagerTest.java @@ -36,7 +36,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_render import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUserRole; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation; diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java index 50e879048..5f76ae15d 100644 --- a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java +++ b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java @@ -50,8 +50,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_render import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.gbp.bridge.domain.PhysicalLocationRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanVni; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2; -- 2.36.6