Adding vxlan tunnel id allocator. 66/266/5
authorJozef Gloncak <jgloncak@cisco.com>
Tue, 9 Feb 2016 14:03:53 +0000 (15:03 +0100)
committerGerrit Code Review <gerrit@fd.io>
Tue, 9 Feb 2016 16:22:39 +0000 (16:22 +0000)
Change-Id: Id638bc0262481921cd42d830e9fc788e76bc3907
Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
vbd/api/src/main/java/io.fd.honeycomb.vbd.api/VxlanTunnelIdAllocator.java [moved from vbd/api/src/main/java/io.fd.honeycomb.vbd.api/VxlanTunnelIdAlocator.java with 62% similarity]
vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/BridgeDomain.java
vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/TopologyMonitor.java
vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/VbdUtil.java
vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/VppModifier.java

@@ -8,10 +8,12 @@
 package io.fd.honeycomb.vbd.api;
 
 
-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.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.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 
-public interface VxlanTunnelIdAlocator {
+public interface VxlanTunnelIdAllocator {
 
     /**
      * Allocate next available vxlan tunnel ID
@@ -19,5 +21,5 @@ public interface VxlanTunnelIdAlocator {
      * @param vpp specify contret vpp for which is next available vxlan id looked for
      * @return next available (in order) vxlan id.
      */
-    Integer nextIdFor(final NodeId vpp);
+    Integer nextIdFor(final KeyedInstanceIdentifier<Node, NodeKey> vpp);
 }
index 114e67c..915e1b4 100644 (file)
@@ -16,6 +16,7 @@ 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 io.fd.honeycomb.vbd.api.VxlanTunnelIdAllocator;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -76,8 +77,6 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
 
     private static final int SOURCE_VPP_INDEX = 0;
     private static final int DESTINATION_VPP_INDEX = 1;
-    private static final String TUNNEL_ID_PREFIX = "vxlan_tunnel";
-    static final String TUNNEL_ID_DEMO = TUNNEL_ID_PREFIX + "0";
     private final KeyedInstanceIdentifier<Topology, TopologyKey> topology;
     @GuardedBy("this")
 
@@ -85,23 +84,26 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
     private final ListenerRegistration<?> reg;
     private final MountPointService mountService;
     private final VppModifier vppModifier;
+    private final VxlanTunnelIdAllocator tunnelIdAllocator;
     private TopologyVbridgeAugment config;
     private final String bridgeDomainName;
     private final String iiBridgeDomainOnVPPRest;
     private Multimap<NodeId, KeyedInstanceIdentifier<Node, NodeKey>> nodesToVpps = ArrayListMultimap.create();
 
     private BridgeDomain(final DataBroker dataBroker, final MountPointService mountService, final KeyedInstanceIdentifier<Topology, TopologyKey> topology,
-            final BindingTransactionChain chain) {
+                         final BindingTransactionChain chain, VxlanTunnelIdAllocator tunnelIdAllocator) {
+        this.bridgeDomainName = topology.getKey().getTopologyId().getValue();
+        this.vppModifier = new VppModifier(mountService, bridgeDomainName);
+
         this.topology = Preconditions.checkNotNull(topology);
         this.chain = Preconditions.checkNotNull(chain);
         this.mountService = mountService;
+        this.tunnelIdAllocator = tunnelIdAllocator;
 
-        this.bridgeDomainName = topology.getKey().getTopologyId().getValue();
         this.iiBridgeDomainOnVPPRest = provideIIBrdigeDomainOnVPPRest();
 
         reg = dataBroker.registerDataTreeChangeListener(
                 new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, topology), this);
-        this.vppModifier = new VppModifier(mountService, bridgeDomainName);
     }
 
     private String provideIIBrdigeDomainOnVPPRest() {
@@ -112,7 +114,8 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
     }
 
     static BridgeDomain create(final DataBroker dataBroker,
-                               MountPointService mountService, final KeyedInstanceIdentifier<Topology, TopologyKey> topology, final BindingTransactionChain chain) {
+                               MountPointService mountService, final KeyedInstanceIdentifier<Topology, TopologyKey> topology, final BindingTransactionChain chain,
+                               final VxlanTunnelIdAllocator tunnelIdAllocator) {
 
         LOG.debug("Wiping operational state of {}", topology);
 
@@ -120,7 +123,7 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
         tx.delete(LogicalDatastoreType.OPERATIONAL, topology);
         tx.submit();
 
-        return new BridgeDomain(dataBroker, mountService, topology, chain);
+        return new BridgeDomain(dataBroker, mountService, topology, chain, tunnelIdAllocator);
     }
 
     synchronized void forceStop() {
@@ -238,10 +241,12 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
 
     private void addTunnel(final NodeId sourceNode) {
         final KeyedInstanceIdentifier<Node, NodeKey> iiToSrcVpp = nodesToVpps.get(sourceNode).iterator().next();
+        final Integer srcVxlanTunnelId = tunnelIdAllocator.nextIdFor(iiToSrcVpp);
         for (Map.Entry<NodeId, KeyedInstanceIdentifier<Node, NodeKey>> nodeToVpp : nodesToVpps.entries()) {
             if (!nodeToVpp.getKey().equals(sourceNode)) {
                 //TODO: check whether returned value from nodesToVpps is not null
                 final KeyedInstanceIdentifier<Node, NodeKey> iiToDstVpp = nodeToVpp.getValue();
+                final Integer dstVxlanTunnelId = tunnelIdAllocator.nextIdFor(iiToDstVpp);
                 final NodeId dstNode = nodeToVpp.getKey();
 
                 final ListenableFuture<List<Optional<Ipv4AddressNoZone>>> ipAddressesFuture = vppModifier.readIpAddressesFromVpps(iiToSrcVpp, iiToDstVpp);
@@ -255,16 +260,16 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
                             if (ipAddressSrcVpp != null && ipAddressDstVpp != null) {
                                 if (ipAddressSrcVpp.isPresent() && ipAddressDstVpp.isPresent()) {
                                     //writing v3po:vxlan container to source node
-                                    vppModifier.createVirtualInterfaceOnVpp(ipAddressSrcVpp.get(), ipAddressDstVpp.get(), iiToSrcVpp);
+                                    vppModifier.createVirtualInterfaceOnVpp(ipAddressSrcVpp.get(), ipAddressDstVpp.get(), iiToSrcVpp, srcVxlanTunnelId);
 
                                     //writing v3po:vxlan container to existing node
-                                    vppModifier.createVirtualInterfaceOnVpp(ipAddressDstVpp.get(), ipAddressSrcVpp.get(), iiToDstVpp);
+                                    vppModifier.createVirtualInterfaceOnVpp(ipAddressDstVpp.get(), ipAddressSrcVpp.get(), iiToDstVpp, dstVxlanTunnelId);
 
-                                    addTerminationPoint(topology.child(Node.class, new NodeKey(dstNode)));
-                                    addTerminationPoint(topology.child(Node.class, new NodeKey(sourceNode)));
+                                    addTerminationPoint(topology.child(Node.class, new NodeKey(dstNode)), dstVxlanTunnelId);
+                                    addTerminationPoint(topology.child(Node.class, new NodeKey(sourceNode)), srcVxlanTunnelId);
 
-                                    addLinkBetweenTerminationPoints(sourceNode, dstNode);
-                                    addLinkBetweenTerminationPoints(dstNode, sourceNode);
+                                    addLinkBetweenTerminationPoints(sourceNode, dstNode, srcVxlanTunnelId, dstVxlanTunnelId);
+                                    addLinkBetweenTerminationPoints(dstNode, sourceNode, srcVxlanTunnelId, dstVxlanTunnelId);
                                 }
                             }
                         }
@@ -279,32 +284,34 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
         }
     }
 
-    private void addLinkBetweenTerminationPoints(final NodeId newVpp, final NodeId odlVpp) {
+    private void addLinkBetweenTerminationPoints(final NodeId newVpp, final NodeId odlVpp,
+                                                 final int srcVxlanTunnelId, final int dstVxlanTunnelId) {
         //TODO clarify how should identifier of link looks like
         final String linkIdStr = newVpp.getValue() + "-" + odlVpp.getValue();
         final LinkId linkId = new LinkId(linkIdStr);
         final KeyedInstanceIdentifier<Link, LinkKey> iiToLink = topology.child(Link.class, new LinkKey(linkId));
         final WriteTransaction wTx = chain.newWriteOnlyTransaction();
-        wTx.put(LogicalDatastoreType.OPERATIONAL, iiToLink, prepareLinkData(newVpp, odlVpp, linkId), true);
+        wTx.put(LogicalDatastoreType.OPERATIONAL, iiToLink, prepareLinkData(newVpp, odlVpp, linkId, srcVxlanTunnelId, dstVxlanTunnelId), true);
         wTx.submit();
     }
 
-    private Link prepareLinkData(final NodeId newVpp, final NodeId oldVpp, final LinkId linkId) {
+    private Link prepareLinkData(final NodeId newVpp, final NodeId oldVpp, final LinkId linkId,
+                                 final int srcVxlanTunnelId, final int dstVxlanTunnelId) {
         final LinkBuilder linkBuilder = new LinkBuilder();
         linkBuilder.setLinkId(linkId);
 
         final SourceBuilder sourceBuilder = new SourceBuilder();
         sourceBuilder.setSourceNode(newVpp);
-        sourceBuilder.setSourceTp(new TpId(TUNNEL_ID_DEMO));
+        sourceBuilder.setSourceTp(new TpId(VbdUtil.provideVxlanId(srcVxlanTunnelId)));
         linkBuilder.setSource(sourceBuilder.build());
 
         final DestinationBuilder destinationBuilder = new DestinationBuilder();
         destinationBuilder.setDestNode(oldVpp);
-        destinationBuilder.setDestTp(new TpId(TUNNEL_ID_DEMO));
+        destinationBuilder.setDestTp(new TpId(VbdUtil.provideVxlanId(dstVxlanTunnelId)));
         linkBuilder.setDestination(destinationBuilder.build());
 
         final LinkVbridgeAugmentBuilder linkVbridgeAugmentBuilder = new LinkVbridgeAugmentBuilder();
-        linkVbridgeAugmentBuilder.setTunnel(new ExternalReference(TUNNEL_ID_DEMO));
+        linkVbridgeAugmentBuilder.setTunnel(new ExternalReference(VbdUtil.provideVxlanId(srcVxlanTunnelId)));
         linkBuilder.addAugmentation(LinkVbridgeAugment.class, linkVbridgeAugmentBuilder.build());
         return linkBuilder.build();
     }
@@ -344,9 +351,9 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
         });
     }
 
-    private void addTerminationPoint(final KeyedInstanceIdentifier<Node, NodeKey> nodeIID) {
+    private void addTerminationPoint(final KeyedInstanceIdentifier<Node, NodeKey> nodeIID, final int vxlanTunnelId) {
         // build data
-        final ExternalReference ref = new ExternalReference(TUNNEL_ID_DEMO);
+        final ExternalReference ref = new ExternalReference(VbdUtil.provideVxlanId(vxlanTunnelId));
         final TunnelInterfaceBuilder iFaceBuilder = new TunnelInterfaceBuilder();
         iFaceBuilder.setTunnelInterface(ref);
 
@@ -355,7 +362,7 @@ final class BridgeDomain implements DataTreeChangeListener<Topology> {
 
         final TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
         tpBuilder.addAugmentation(TerminationPointVbridgeAugment.class, tpAugmentBuilder.build());
-        tpBuilder.setTpId(new TpId(TUNNEL_ID_DEMO));
+        tpBuilder.setTpId(new TpId(VbdUtil.provideVxlanId(vxlanTunnelId)));
         final TerminationPoint tp = tpBuilder.build();
 
         // process data
index 213ff66..dfab2e8 100644 (file)
@@ -9,6 +9,7 @@
 package io.fd.honeycomb.vbd.impl;
 
 import com.google.common.base.Preconditions;
+import io.fd.honeycomb.vbd.api.VxlanTunnelIdAllocator;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -26,6 +27,8 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListen
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.topology.types.VbridgeTopology;
 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.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,10 +44,12 @@ final class TopologyMonitor implements DataTreeChangeListener<VbridgeTopology>,
     private final Map<TopologyKey, BridgeDomain> domains = new HashMap<>();
     private final DataBroker dataBroker;
     private final MountPointService mountService;
+    private static final VxlanTunnelIdAllocator tunnelIdAllocator = new VxlanTunnelIdAllocatorImpl();
 
     public TopologyMonitor(DataBroker dataBroker, MountPointService mountService) {
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.mountService = Preconditions.checkNotNull(mountService);
+
     }
 
     @Override
@@ -118,7 +123,7 @@ final class TopologyMonitor implements DataTreeChangeListener<VbridgeTopology>,
             }
         });
 
-        final BridgeDomain domain = BridgeDomain.create(dataBroker, mountService, topology, chain);
+        final BridgeDomain domain = BridgeDomain.create(dataBroker, mountService, topology, chain, tunnelIdAllocator);
         domains.put(topology.getKey(), domain);
 
         LOG.debug("Bridge domain {} for {} started", domain, topology);
@@ -159,4 +164,26 @@ final class TopologyMonitor implements DataTreeChangeListener<VbridgeTopology>,
 
         LOG.debug("Topology monitor {} shut down completed", this);
     }
+
+    public static class VxlanTunnelIdAllocatorImpl implements VxlanTunnelIdAllocator {
+
+        private final Map<KeyedInstanceIdentifier<Node, NodeKey>, Integer> vppIIToNextTunnelId;
+
+        VxlanTunnelIdAllocatorImpl() {
+            vppIIToNextTunnelId = new HashMap<>();
+        }
+
+        @Override
+        public synchronized Integer nextIdFor(final KeyedInstanceIdentifier<Node, NodeKey> iiToVPP) {
+            if(vppIIToNextTunnelId.containsKey(iiToVPP)) {
+                final int value = vppIIToNextTunnelId.get(iiToVPP);
+                vppIIToNextTunnelId.put(iiToVPP, value + 1);
+                return value + 1;
+            } else {
+                vppIIToNextTunnelId.put(iiToVPP, 0);
+                return 0;
+            }
+        }
+
+    }
 }
index ecc9703..2a29d7b 100644 (file)
@@ -17,6 +17,9 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class VbdUtil {
 
+    private static final String TUNNEL_ID_PREFIX = "vxlan_tunnel";
+
+
     private VbdUtil() {
         throw new UnsupportedOperationException("Can't instantiate util class");
     }
@@ -33,5 +36,9 @@ public class VbdUtil {
         return null;
     }
 
+    static String provideVxlanId(final int vxlanTunnelId) {
+        return TUNNEL_ID_PREFIX + vxlanTunnelId;
+    }
+
 
 }
index 489f6c7..3378e68 100644 (file)
@@ -146,15 +146,16 @@ public class VppModifier {
         return resultFuture;
     }
 
-    void createVirtualInterfaceOnVpp(final Ipv4AddressNoZone ipSrc, final Ipv4AddressNoZone ipDst, final KeyedInstanceIdentifier<Node, NodeKey> iiToVpp) {
+    void createVirtualInterfaceOnVpp(final Ipv4AddressNoZone ipSrc, final Ipv4AddressNoZone ipDst, final KeyedInstanceIdentifier<Node, NodeKey> iiToVpp,
+                                     final Integer vxlanTunnelId) {
         final Vxlan vxlanData = prepareVxlan(ipSrc, ipDst);
-        final Interface intfData = prepareVirtualInterfaceData(vxlanData);
+        final Interface intfData = prepareVirtualInterfaceData(vxlanData, vxlanTunnelId);
 
         final DataBroker vppDataBroker = VbdUtil.resolveDataBrokerForMountPoint(iiToVpp, mountService);
         if (vppDataBroker != null) {
             final WriteTransaction wTx = vppDataBroker.newWriteOnlyTransaction();
             final KeyedInstanceIdentifier<Interface, InterfaceKey> iiToInterface
-                    = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(BridgeDomain.TUNNEL_ID_DEMO));
+                    = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(VbdUtil.provideVxlanId(vxlanTunnelId)));
             wTx.put(LogicalDatastoreType.CONFIGURATION, iiToInterface, intfData);
             final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
             Futures.addCallback(submitFuture, new FutureCallback<Void>() {
@@ -169,14 +170,14 @@ public class VppModifier {
                 }
             });
         } else {
-            LOG.debug("Writing virtual interface {} to VPP {} wasn't successfull because missing data broker.", BridgeDomain.TUNNEL_ID_DEMO, iiToVpp);
+            LOG.debug("Writing virtual interface {} to VPP {} wasn't successfull because missing data broker.", VbdUtil.provideVxlanId(vxlanTunnelId), iiToVpp);
         }
     }
 
-    private Interface prepareVirtualInterfaceData(final Vxlan vxlan) {
+    private Interface prepareVirtualInterfaceData(final Vxlan vxlan, Integer vxlanTunnelId) {
         final InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
         //TODO implement tunnel counter
-        interfaceBuilder.setName(BridgeDomain.TUNNEL_ID_DEMO);
+        interfaceBuilder.setName(VbdUtil.provideVxlanId(vxlanTunnelId));
         interfaceBuilder.setType(VxlanTunnel.class);
         VppInterfaceAugmentationBuilder vppInterfaceAugmentationBuilder = new VppInterfaceAugmentationBuilder();
         vppInterfaceAugmentationBuilder.setVxlan(vxlan);