summaryrefslogtreecommitdiffstats
path: root/vbd
diff options
context:
space:
mode:
authorJozef Gloncak <jgloncak@cisco.com>2016-02-03 11:18:51 +0100
committerDave Wallace <dwallacelf@gmail.com>2016-02-04 13:08:28 +0000
commit809e3e17a7582e56404c95e645914dd341fa379e (patch)
tree6be38cf505bd319d631fb8a87825beb1ddc96c0f /vbd
parentafb65be5ea2e05319bf4241856231a2a5d8646ca (diff)
Adding termination point to VBD on VPP.
Creation request from UI for creating new termination point cause that interface on VPP is added to virtual bridge domain. Change-Id: I73910e31250c81e9e8baac40072926bdfc71ff22 Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
Diffstat (limited to 'vbd')
-rw-r--r--vbd/api/src/main/yang/vbridge-topology.yang1
-rw-r--r--vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/BridgeDomain.java111
-rw-r--r--vbd/impl/vbridge-workflow.txt10
3 files changed, 94 insertions, 28 deletions
diff --git a/vbd/api/src/main/yang/vbridge-topology.yang b/vbd/api/src/main/yang/vbridge-topology.yang
index 901907387..e0ff290f4 100644
--- a/vbd/api/src/main/yang/vbridge-topology.yang
+++ b/vbd/api/src/main/yang/vbridge-topology.yang
@@ -118,6 +118,7 @@ module vbridge-topology {
}
augment "/nt:network-topology/nt:topology/nt:node/nt:termination-point" {
+ ext:augment-identifier "termination-point-vbridge-augment";
when "../bridge-member";
choice interface-type {
diff --git a/vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/BridgeDomain.java b/vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/BridgeDomain.java
index 6105cb26d..82558684f 100644
--- a/vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/BridgeDomain.java
+++ b/vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/BridgeDomain.java
@@ -10,6 +10,8 @@ package io.fd.honeycomb.vbd.impl;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
@@ -27,15 +29,25 @@ import org.opendaylight.controller.md.sal.binding.api.MountPointService;
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.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+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.params.xml.ns.yang.external.reference.rev160129.ExternalReference;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Vpp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBasedBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.NodeVbridgeAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TerminationPointVbridgeAugment;
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.topology.rev160129.network.topology.topology.node.BridgeMember;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.node.BridgeMemberBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.node.termination.point.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.node.termination.point._interface.type.UserInterface;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
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;
@@ -43,6 +55,7 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.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.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNode;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -68,6 +81,7 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
private final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain> iiBridgeDomainOnVPP;
private final String iiBridgeDomainOnVPPRest;
private final DataBroker dataBroker;
+ private Multimap<NodeId, InstanceIdentifier<?>> nodesToVpps = ArrayListMultimap.create();
private BridgeDomain(final DataBroker dataBroker, final MountPointService mountService, final KeyedInstanceIdentifier<Topology, TopologyKey> topology,
final BindingTransactionChain chain) {
@@ -148,7 +162,7 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
LOG.debug("Topology {} modified child {}", topology, child);
if (Node.class.isAssignableFrom(child.getDataType())) {
- modifyNode((DataObjectModification<Node>) child, newConfig.getDataAfter());
+ modifyNode((DataObjectModification<Node>) child);
}
}
@@ -174,27 +188,84 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
}
}
- private void modifyNode(final DataObjectModification<Node> child, final TopologyVbridgeAugment topologyVbridgeAugment) {
- switch (child.getModificationType()) {
+ private void modifyNode(final DataObjectModification<Node> nodeMod) {
+ switch (nodeMod.getModificationType()) {
case DELETE:
- LOG.debug("Topology {} node {} deleted", topology, child.getIdentifier());
+ LOG.debug("Topology {} node {} deleted", topology, nodeMod.getIdentifier());
// FIXME: do something
break;
case SUBTREE_MODIFIED:
- LOG.debug("Topology {} node {} modified", topology, child.getIdentifier());
- // FIXME: do something
+ LOG.debug("Topology {} node {} modified", topology, nodeMod.getIdentifier());
+ for (DataObjectModification<? extends DataObject> nodeChild : nodeMod.getModifiedChildren()) {
+ if (TerminationPoint.class.isAssignableFrom(nodeChild.getDataType())) {
+ modifyTerminationPoint((DataObjectModification<TerminationPoint>) nodeChild,nodeMod.getDataAfter().getNodeId());
+ }
+ }
break;
case WRITE:
- LOG.debug("Topology {} node {} created", topology, child.getIdentifier());
- createNode(child.getDataAfter(), topologyVbridgeAugment);
+ LOG.debug("Topology {} node {} created", topology, nodeMod.getIdentifier());
+ createNode(nodeMod.getDataAfter());
break;
default:
- LOG.warn("Unhandled node modification {} in topology {}", child, topology);
+ LOG.warn("Unhandled node modification {} in topology {}", nodeMod, topology);
break;
}
}
- private void createNode(final Node node, final TopologyVbridgeAugment topologyVbridgeAugment) {
+ private void modifyTerminationPoint(final DataObjectModification<TerminationPoint> nodeChild, final NodeId nodeId) {
+ final TerminationPoint terminationPoint = nodeChild.getDataAfter();
+ final TerminationPointVbridgeAugment termPointVbridgeAug = terminationPoint.getAugmentation(TerminationPointVbridgeAugment.class);
+ if (termPointVbridgeAug != null) {
+ final Collection<InstanceIdentifier<?>> instanceIdentifiersVPP = nodesToVpps.get(nodeId);
+ //TODO: probably iterate via all instance identifiers.
+ if (!instanceIdentifiersVPP.isEmpty()) {
+ final DataBroker dataBroker = resolveDataBrokerForMountPoint(instanceIdentifiersVPP.iterator().next());
+ addInterfaceToBridgeDomainOnVpp(dataBroker, termPointVbridgeAug);
+ }
+ }
+ }
+
+ private void addInterfaceToBridgeDomainOnVpp(final DataBroker vppDataBroker, final TerminationPointVbridgeAugment termPointVbridgeAug) {
+ final InterfaceType interfaceType = termPointVbridgeAug.getInterfaceType();
+ if (interfaceType instanceof UserInterface) {
+ //REMARK: according contract in YANG model this should be URI to data on mount point (accroding to RESTCONF)
+ //It was much more easier to just await concrete interface name, thus isn't necessary parse it (splitting on '/')
+ final ExternalReference userInterface = ((UserInterface) interfaceType).getUserInterface();
+ final KeyedInstanceIdentifier<Interface, InterfaceKey> iiToVpp =
+ InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(userInterface.getValue()));
+ InstanceIdentifier<L2> iiToV3poL2 = iiToVpp.augmentation(VppInterfaceAugmentation.class).child(L2.class);
+ LOG.debug("Writing L2 data to configuration DS to concrete interface.");
+ final WriteTransaction wTx = vppDataBroker.newWriteOnlyTransaction();
+ wTx.put(LogicalDatastoreType.CONFIGURATION, iiToV3poL2, prepareL2Data());
+ wTx.submit();
+ }
+ }
+
+ private L2 prepareL2Data() {
+ final L2Builder l2Builder = new L2Builder();
+ final BridgeBasedBuilder bridgeBasedBuilder = new BridgeBasedBuilder();
+ bridgeBasedBuilder.setSplitHorizonGroup((short) 0);
+ bridgeBasedBuilder.setBridgedVirtualInterface(false);
+ bridgeBasedBuilder.setBridgeDomain(bridgeDomainName);
+ l2Builder.setInterconnection(bridgeBasedBuilder.build());
+ return l2Builder.build();
+ }
+
+
+ private DataBroker resolveDataBrokerForMountPoint(final InstanceIdentifier<?> iiToMountPoint) {
+ final Optional<MountPoint> vppMountPointOpt = mountService.getMountPoint(iiToMountPoint);
+ if (vppMountPointOpt.isPresent()) {
+ final MountPoint vppMountPoint = vppMountPointOpt.get();
+ final Optional<DataBroker> dataBrokerOpt = vppMountPoint.getService(DataBroker.class);
+ if (dataBrokerOpt.isPresent()) {
+ return dataBrokerOpt.get();
+ }
+ }
+ return null;
+ }
+
+ private void createNode(final Node node) {
for (SupportingNode supportingNode : node.getSupportingNode()) {
final NodeId nodeMount = supportingNode.getNodeRef();
final TopologyId topologyMount = supportingNode.getTopologyRef();
@@ -203,20 +274,16 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
.create(NetworkTopology.class)
.child(Topology.class, new TopologyKey(topologyMount))
.child(Node.class, new NodeKey(nodeMount));
- final Optional<MountPoint> vppMountOption = mountService.getMountPoint(iiToMount);
- if (vppMountOption.isPresent()) {
- final MountPoint vppMount = vppMountOption.get();
- addVppToBridgeDomain(topologyVbridgeAugment, vppMount, node);
- }
+ nodesToVpps.put(node.getNodeId(), iiToMount);
+ final DataBroker dataBrokerOfMount = resolveDataBrokerForMountPoint(iiToMount);
+ addVppToBridgeDomain(dataBrokerOfMount, node);
}
}
- private void addVppToBridgeDomain(final TopologyVbridgeAugment topologyVbridgeAugment, final MountPoint vppMount, final Node node) {
- final Optional<DataBroker> dataBrokerOpt = vppMount.getService(DataBroker.class);
- if (dataBrokerOpt.isPresent()) {
- final DataBroker vppDataBroker = dataBrokerOpt.get();
+ private void addVppToBridgeDomain(final DataBroker vppDataBroker, final Node node) {
+ if (vppDataBroker != null) {
final WriteTransaction wTx = vppDataBroker.newWriteOnlyTransaction();
- wTx.put(LogicalDatastoreType.OPERATIONAL, iiBridgeDomainOnVPP, prepareNewBridgeDomainData(topologyVbridgeAugment));
+ wTx.put(LogicalDatastoreType.CONFIGURATION, iiBridgeDomainOnVPP, prepareNewBridgeDomainData());
final CheckedFuture<Void, TransactionCommitFailedException> addVppToBridgeDomainFuture = wTx.submit();
addSupportingBridgeDomain(addVppToBridgeDomainFuture, node);
}
@@ -244,8 +311,8 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
}
private org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain
- prepareNewBridgeDomainData(TopologyVbridgeAugment topologyVbridgeAugment) {
- final BridgeDomainBuilder bridgeDomainBuilder = new BridgeDomainBuilder(topologyVbridgeAugment);
+ prepareNewBridgeDomainData() {
+ final BridgeDomainBuilder bridgeDomainBuilder = new BridgeDomainBuilder(config);
bridgeDomainBuilder.setName(topology.getKey().getTopologyId().getValue());
return bridgeDomainBuilder.build();
}
diff --git a/vbd/impl/vbridge-workflow.txt b/vbd/impl/vbridge-workflow.txt
index 86ba544f4..9f93e6fd4 100644
--- a/vbd/impl/vbridge-workflow.txt
+++ b/vbd/impl/vbridge-workflow.txt
@@ -32,7 +32,7 @@ Prerequisite: configured netconf-node-topology
- bridge-member container
- supporting-node pointing to the VPP node in the
netconf-node-topology
-
+
B) The Controller App receives a DataTreeChangeNotification about the
node being added, and:
@@ -46,7 +46,7 @@ Prerequisite: configured netconf-node-topology
datastore. The leaf contains a RESTCONF-encoded instance
identifier of the bridge domain created in the VPP, relative to
that VPP's mount point.
-
+
3) Assigning a physical VPP interface into a Virtual Bridge Domain
Prerequisite: The VPP itself has been added to the Virtual Bridge
Domain
@@ -54,9 +54,7 @@ Prerequisite: configured netconf-node-topology
A) The UI creates a 'termination-point' inside the 'node' added in 2),
with:
- - user-interface, containing RESTCONF-encoded instance identifier
- of the VPP interface, relative to that VPP's mount point in config
- data store.
+ - interface name.
B) The Controller App receives a notification of this being done and:
- looks if the VPP is connected, if it is, the app will:
@@ -64,7 +62,7 @@ Prerequisite: configured netconf-node-topology
Inverse operations are achieved by the UI deleting the corresponding nodes in
the Controller's configuration data store.
-
+
Virtual Bridge Domain tunnel management
---------------------------------------