NETVIRT-1122 - L3 ping between pods not working 96/67396/24
authorFaseela K <faseela.k@ericsson.com>
Fri, 16 Feb 2018 08:30:11 +0000 (14:00 +0530)
committerSam Hague <shague@redhat.com>
Sun, 4 Mar 2018 02:18:33 +0000 (02:18 +0000)
Change-Id: Ia89276382b27292f5891d958851380a4637b0508
Signed-off-by: Faseela K <faseela.k@ericsson.com>
coe/api/pom.xml
coe/api/src/main/yang/pod-meta.yang [new file with mode: 0644]
coe/impl/pom.xml
coe/impl/src/main/java/org/opendaylight/netvirt/coe/caches/PodsCache.java [new file with mode: 0644]
coe/impl/src/main/java/org/opendaylight/netvirt/coe/listeners/PodListener.java
coe/impl/src/main/java/org/opendaylight/netvirt/coe/listeners/TerminationPointStateListener.java [new file with mode: 0644]
coe/impl/src/main/java/org/opendaylight/netvirt/coe/utils/CoeUtils.java
coe/impl/src/main/resources/org/opendaylight/blueprint/coe-renderer.xml
vpnmanager/api/src/main/yang/odl-l3vpn.yang
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/arp/responder/ArpResponderHandler.java

index 846fd7bd8f4590ffe58d49df826113abd2dea564..c74105b1ee5af2cd91f1dd12a5896736cbd35c2b 100644 (file)
@@ -26,6 +26,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <groupId>org.opendaylight.mdsal</groupId>
             <artifactId>yang-binding</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>ietf-yang-types-20130715</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-common</artifactId>
diff --git a/coe/api/src/main/yang/pod-meta.yang b/coe/api/src/main/yang/pod-meta.yang
new file mode 100644 (file)
index 0000000..5c96b3c
--- /dev/null
@@ -0,0 +1,29 @@
+module pod-meta {
+    namespace "urn:opendaylight:netvirt:coe:meta";
+    prefix "coemeta";
+
+    import ietf-yang-types {
+        prefix yang;
+        revision-date "2013-07-15";
+    }
+
+    revision "2018-01-18" {
+        description "Coe Meta Information";
+    }
+
+    container podidentifier-info {
+        description "Contains the list of podnames to poduuid mapping";
+
+        list pod-identifier {
+            key pod-name;
+            leaf pod-name {
+                type string;
+            }
+
+            leaf pod-uuid {
+                type instance-identifier;
+                description "reference to a pod";
+            }
+        }
+    }
+}
\ No newline at end of file
index 38e9c45480c9f8f3ca2fb0a1033cf09ec53f5bc4..c7df9a13cba43e26d52e89b2f89d551562aeeda4 100644 (file)
@@ -50,6 +50,16 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <artifactId>elanmanager-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>vpnmanager-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.ovsdb</groupId>
+            <artifactId>utils.southbound-utils</artifactId>
+            <version>${ovsdb.version}</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/coe/impl/src/main/java/org/opendaylight/netvirt/coe/caches/PodsCache.java b/coe/impl/src/main/java/org/opendaylight/netvirt/coe/caches/PodsCache.java
new file mode 100644 (file)
index 0000000..d14a965
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. 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.netvirt.coe.caches;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.mdsalutil.cache.DataObjectCache;
+import org.opendaylight.infrautils.caches.CacheProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.Coe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.coe.Pods;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@Singleton
+public class PodsCache extends DataObjectCache<Pods> {
+    @Inject
+    public PodsCache(DataBroker dataBroker, CacheProvider cacheProvider) {
+        super(Pods.class, dataBroker, LogicalDatastoreType.CONFIGURATION,
+                InstanceIdentifier.create(Coe.class).child(Pods.class), cacheProvider);
+    }
+}
index 48f631cb47d3d16bccd4fc20a0852e49a2fe6fdf..c52c90547abb4806336b96ace79dab2196820f95 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2017 - 2018 Ericsson India Global Services Pvt Ltd. 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,
@@ -9,8 +9,10 @@
 package org.opendaylight.netvirt.coe.listeners;
 
 import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.Callable;
@@ -28,6 +30,8 @@ import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.netvirt.coe.utils.CoeUtils;
+import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.Coe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.coe.Pods;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.pod_attributes.Interface;
@@ -42,8 +46,8 @@ public class PodListener implements DataTreeChangeListener<Pods> {
 
     private static final Logger LOG = LoggerFactory.getLogger(PodListener.class);
     private ListenerRegistration<PodListener> listenerRegistration;
-    private final ManagedNewTransactionRunner txRunner;
     private final JobCoordinator jobCoordinator;
+    private final ManagedNewTransactionRunner txRunner;
 
     @Inject
     public PodListener(final DataBroker dataBroker, JobCoordinator jobCoordinator) {
@@ -94,16 +98,17 @@ public class PodListener implements DataTreeChangeListener<Pods> {
         Interface podInterfaceAfter = dataObjectModification.getDataAfter();
         switch (dataObjectModification.getModificationType()) {
             case DELETE:
-                remove(podsBefore, podInterfaceBefore);
+                remove(rootIdentifier, podsBefore, podInterfaceBefore);
                 break;
             case SUBTREE_MODIFIED:
-                update(pods, podsBefore, podInterfaceAfter);
+                update(rootIdentifier, pods, podsBefore, podInterfaceBefore, podInterfaceAfter);
                 break;
             case WRITE:
                 if (podInterfaceBefore == null) {
-                    add(pods, podInterfaceAfter);
+                    add(rootIdentifier, pods, podInterfaceAfter);
                 } else {
-                    update(pods, podsBefore, podInterfaceAfter);
+                    update(rootIdentifier, pods, podsBefore, podInterfaceBefore,
+                            podInterfaceAfter);
                 }
                 break;
             default:
@@ -112,33 +117,33 @@ public class PodListener implements DataTreeChangeListener<Pods> {
         }
     }
 
-    private void add(Pods pods, Interface podInterface) {
+    private void add(InstanceIdentifier<Pods> instanceIdentifier, Pods pods, Interface podInterface) {
         LOG.trace("Pod added {}",pods);
         if (pods.getNetworkNS() == null || pods.getHostIpAddress() == null) {
             LOG.warn("pod {} added with insufficient information to process", pods.getName());
             return;
         }
-        // TODO use infrautils caching mechanism to add this info to cache.
-
-        jobCoordinator.enqueueJob(pods.getName(), new PodConfigAddWorker(txRunner, pods, podInterface));
+        jobCoordinator.enqueueJob(pods.getName(), new PodConfigAddWorker(txRunner, instanceIdentifier,
+                pods, podInterface));
     }
 
-    private void update(Pods podsAfter, Pods podsBefore, Interface podInterfaceAfter) {
+    private void update(InstanceIdentifier<Pods> instanceIdentifier, Pods podsAfter, Pods podsBefore,
+                        Interface podInterfaceBefore, Interface podInterfaceAfter) {
         LOG.trace("Pod updated before :{}, after :{}",podsBefore, podsAfter);
-        if (!Objects.equals(podsAfter.getNetworkNS(), podsBefore.getNetworkNS())
-                || !Objects.equals(podsAfter.getHostIpAddress(), podsBefore.getHostIpAddress())) {
-            if (podsBefore.getNetworkNS() != null || podsBefore.getHostIpAddress() != null) {
+        if (!Objects.equals(podsAfter.getHostIpAddress(), podsBefore.getHostIpAddress())
+                || !Objects.equals(podInterfaceBefore.getIpAddress(), podInterfaceAfter.getIpAddress())) {
+            //if (podsBefore.getNetworkNS() != null || podsBefore.getHostIpAddress() != null) {
                 // Case where pod is moving from one namespace to another
                 // issue a delete of all previous configuration, and add the new one.
-                jobCoordinator.enqueueJob(podsAfter.getName(), new PodConfigRemoveWorker(txRunner, podsBefore));
-            }
-            jobCoordinator.enqueueJob(podsAfter.getName(), new PodConfigAddWorker(txRunner, podsAfter,
-                    podInterfaceAfter));
+                //jobCoordinator.enqueueJob(podsAfter.getName(), new PodConfigRemoveWorker(txRunner, podsBefore));
+            //}
+            jobCoordinator.enqueueJob(podsAfter.getName(), new PodConfigAddWorker(txRunner, instanceIdentifier,
+                    podsAfter, podInterfaceAfter));
         }
-        // TODO use infrautils caching mechanism to add this info to cache.
     }
 
-    private void remove(Pods pods, Interface podInterface) {
+    private void remove(InstanceIdentifier<Pods> instanceIdentifier,
+                        Pods pods, Interface podInterface) {
         LOG.trace("Pod removed {}", pods);
         if (pods.getNetworkNS() == null || pods.getHostIpAddress() == null) {
             LOG.warn("pod {} deletion without a valid network id {}", podInterface.getUid().getValue());
@@ -149,21 +154,25 @@ public class PodListener implements DataTreeChangeListener<Pods> {
     }
 
     private static class PodConfigAddWorker implements Callable<List<ListenableFuture<Void>>> {
+        InstanceIdentifier<Pods> podsInstanceIdentifier;
         private final Pods pods;
         private final Interface podInterface;
         private final ManagedNewTransactionRunner txRunner;
 
-        PodConfigAddWorker(ManagedNewTransactionRunner txRunner, Pods pods, Interface podInterface) {
+        PodConfigAddWorker(ManagedNewTransactionRunner txRunner, InstanceIdentifier<Pods> podsInstanceIdentifier,
+                           Pods pods, Interface podInterface) {
             this.pods = pods;
             this.podInterface = podInterface;
             this.txRunner = txRunner;
+            this.podsInstanceIdentifier = podsInstanceIdentifier;
         }
 
         @Override
         public List<ListenableFuture<Void>> call() {
             LOG.trace("Adding Pod : {}", podInterface);
             String interfaceName = CoeUtils.buildInterfaceName(pods.getNetworkNS(), pods.getName());
-            return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(tx ->  {
                 String nodeIp = String.valueOf(pods.getHostIpAddress().getValue());
                 ElanInstance elanInstance = CoeUtils.createElanInstanceForTheFirstPodInTheNetwork(
                         pods.getNetworkNS(), nodeIp, podInterface, tx);
@@ -172,7 +181,17 @@ public class PodListener implements DataTreeChangeListener<Pods> {
                 LOG.debug("Creating ELAN Interface for pod {}", interfaceName);
                 CoeUtils.createElanInterface(portInterfaceName,
                         elanInstance.getElanInstanceName(), tx);
+                LOG.debug("Creating VPN instance for namespace {}", pods.getNetworkNS());
+                List<String> rd = Arrays.asList("100:1");
+                CoeUtils.createVpnInstance(pods.getNetworkNS(), rd, null, null,
+                        VpnInstance.Type.L3, 0, IpVersionChoice.IPV4, tx);
             }));
+            if (podInterface.getIpAddress() != null) {
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                    CoeUtils.createPodNameToPodUuidMap(interfaceName, podsInstanceIdentifier, tx);
+                }));
+            }
+            return futures;
         }
     }
 
@@ -180,23 +199,32 @@ public class PodListener implements DataTreeChangeListener<Pods> {
         private final Pods pods;
         private final ManagedNewTransactionRunner txRunner;
 
-        PodConfigRemoveWorker(ManagedNewTransactionRunner txRunner, Pods pods) {
+
+        PodConfigRemoveWorker(ManagedNewTransactionRunner txRunner,
+                              Pods pods) {
             this.pods = pods;
             this.txRunner = txRunner;
         }
 
         @Override
         public List<ListenableFuture<Void>> call() {
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
             String podInterfaceName = CoeUtils.buildInterfaceName(pods.getNetworkNS(), pods.getName());
-            LOG.trace("Deleting Pod : {}", podInterfaceName);
-            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                LOG.trace("Deleting Pod : {}", podInterfaceName);
+                LOG.debug("Deleting VPN Interface for pod {}", podInterfaceName);
+                CoeUtils.deleteVpnInterface(podInterfaceName, tx);
                 LOG.debug("Deleting ELAN Interface for pod {}", podInterfaceName);
                 CoeUtils.deleteElanInterface(podInterfaceName, tx);
                 LOG.info("interface deletion for pod {}", podInterfaceName);
                 CoeUtils.deleteOfPortInterface(podInterfaceName, tx);
-                // TODO delete elan-instance if this is the last pod in the network
-                // TODO use infrautils cache to maintain this mapping and to decide on elan-instance deletion
+                // TODO delete elan-instance if this is the last pod in the host
+                // TODO delete vpn-instance if this is the last pod in the network
+            }));
+            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                CoeUtils.deletePodNameToPodUuidMap(podInterfaceName, tx);
             }));
+            return futures;
         }
     }
 }
diff --git a/coe/impl/src/main/java/org/opendaylight/netvirt/coe/listeners/TerminationPointStateListener.java b/coe/impl/src/main/java/org/opendaylight/netvirt/coe/listeners/TerminationPointStateListener.java
new file mode 100644 (file)
index 0000000..a99d83f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. 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.netvirt.coe.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.listeners.AbstractSyncDataTreeChangeListener;
+import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.netvirt.coe.caches.PodsCache;
+import org.opendaylight.netvirt.coe.utils.CoeUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.coe.Pods;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+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.network.topology.Topology;
+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.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class TerminationPointStateListener extends
+        AbstractSyncDataTreeChangeListener<OvsdbTerminationPointAugmentation> {
+    private static final Logger LOG = LoggerFactory.getLogger(TerminationPointStateListener.class);
+    private final JobCoordinator coordinator;
+    private final PodsCache  podsCache;
+    private final DataTreeEventCallbackRegistrar eventCallbacks;
+    private final ManagedNewTransactionRunner txRunner;
+
+    @Inject
+    public TerminationPointStateListener(DataBroker dataBroker, final JobCoordinator coordinator,
+                                         PodsCache podsCache, DataTreeEventCallbackRegistrar eventCallbacks) {
+        super(dataBroker, LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).child(Node.class)
+                        .child(TerminationPoint.class).augmentation(OvsdbTerminationPointAugmentation.class).build());
+        this.coordinator = coordinator;
+        this.podsCache = podsCache;
+        this.eventCallbacks = eventCallbacks;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+    }
+
+    @Override
+    public void remove(OvsdbTerminationPointAugmentation tpOld) {
+       // DO nothing
+    }
+
+    @Override
+    public void update(@Nullable OvsdbTerminationPointAugmentation tpOld, OvsdbTerminationPointAugmentation tpNew) {
+        LOG.debug("Received Update DataChange Notification for ovsdb termination point {}", tpNew.getName());
+
+        Pair<String, String> tpNewDetails = CoeUtils.getAttachedInterfaceAndMac(tpNew);
+        Pair<String, String> tpOldDetails = CoeUtils.getAttachedInterfaceAndMac(tpOld);
+
+        if (!Objects.equals(tpNewDetails, tpOldDetails)) {
+            String interfaceName = tpNewDetails.getLeft();
+            String macAddress = tpNewDetails.getRight();
+            if (interfaceName != null && macAddress != null) {
+                LOG.debug("Detected external interface-id {} and attached mac address {} for {}", interfaceName,
+                        macAddress, tpNew.getName());
+                eventCallbacks.onAddOrUpdate(LogicalDatastoreType.OPERATIONAL,
+                    CoeUtils.getPodMetaInstanceId(interfaceName), (unused, alsoUnused) -> {
+                        LOG.info("Pod configuration {} detected for termination-point {},"
+                            + "proceeding with l2 and l3 configurations", interfaceName, tpNew.getName());
+                        List<ListenableFuture<Void>> futures = new ArrayList<>();
+                        futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+                            InstanceIdentifier<Pods> instanceIdentifier = CoeUtils.getPodUUIDforPodName(interfaceName,
+                                    tx);
+                            Pods pods = podsCache.get(instanceIdentifier).get();
+                            if (pods != null) {
+                                IpAddress podIpAddress = pods.getInterface().get(0).getIpAddress();
+                                CoeUtils.createVpnInterface(pods.getNetworkNS(), pods, interfaceName, macAddress,
+                                        false, tx);
+                                CoeUtils.updateElanInterfaceWithStaticMac(macAddress, podIpAddress, interfaceName, tx);
+                            }
+                        }));
+                        return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
+                    });
+            }
+        }
+    }
+
+    @Override
+    public void add(OvsdbTerminationPointAugmentation tpNew) {
+        update(null, tpNew);
+    }
+}
index 475b6d923d59f25bce718f7e4bf0e3aee189064b..ccc5221c3ffa68b2801dac04d23418255c12d535 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2017 - 2018 Ericsson India Global Services Pvt Ltd. 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,
@@ -8,20 +8,55 @@
 
 package org.opendaylight.netvirt.coe.utils;
 
-import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableBiMap;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 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.netvirt.neutronvpn.api.enums.IpVersionChoice;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNamesBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNamesKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 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.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.NetworkAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.coe.Pods;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.meta.rev180118.PodidentifierInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.meta.rev180118.podidentifier.info.PodIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.meta.rev180118.podidentifier.info.PodIdentifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.meta.rev180118.podidentifier.info.PodIdentifierKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeBase;
@@ -35,6 +70,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntriesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -99,13 +144,58 @@ public final class CoeUtils {
                                            WriteTransaction wrtConfigTxn) {
         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
                 .class, new ElanInterfaceKey(elanInterfaceName)).build();
-        // TODO set static mac entries based on pod interface mac
         ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
                 .setName(elanInterfaceName).setKey(new ElanInterfaceKey(elanInterfaceName)).build();
         wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, id, elanInterface);
         LOG.debug("Creating new ELAN Interface {}", elanInterface);
     }
 
+    public static void updateElanInterfaceWithStaticMac(String macAddress, IpAddress ipAddress,
+                                           String elanInterfaceName,
+                                           WriteTransaction wrtConfigTxn) {
+        InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
+                .class, new ElanInterfaceKey(elanInterfaceName)).build();
+        PhysAddress physAddress = PhysAddress.getDefaultInstance(macAddress);
+        List<StaticMacEntries> staticMacEntriesList = new ArrayList<>();
+        StaticMacEntries staticMacEntries = new StaticMacEntriesBuilder().setKey(new StaticMacEntriesKey(
+                physAddress)).setMacAddress(physAddress).setIpPrefix(ipAddress).build();
+        staticMacEntriesList.add(staticMacEntries);
+        ElanInterface elanInterface = new ElanInterfaceBuilder().setName(elanInterfaceName)
+                .setKey(new ElanInterfaceKey(elanInterfaceName)).setStaticMacEntries(staticMacEntriesList).build();
+        wrtConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, id, elanInterface);
+        LOG.debug("Updating ELAN Interface with static mac {}", elanInterface);
+    }
+
+    public static void createPodNameToPodUuidMap(String podName, InstanceIdentifier<Pods> pod,
+                                                 WriteTransaction writeTransaction) {
+        InstanceIdentifier<PodIdentifier> id = InstanceIdentifier.builder(PodidentifierInfo.class)
+                .child(PodIdentifier.class, new PodIdentifierKey(podName)).build();
+        PodIdentifier podIdentifier = new PodIdentifierBuilder().setKey(new PodIdentifierKey(podName))
+                .setPodName(podName).setPodUuid(pod).build();
+        writeTransaction.put(LogicalDatastoreType.OPERATIONAL, id, podIdentifier);
+        LOG.debug("Creating podnametouuid map {} to {}", podName, pod);
+    }
+
+    public static void deletePodNameToPodUuidMap(String podName,
+                                                 WriteTransaction writeTransaction) {
+        InstanceIdentifier<PodIdentifier> id = InstanceIdentifier.builder(PodidentifierInfo.class)
+                .child(PodIdentifier.class, new PodIdentifierKey(podName)).build();
+        writeTransaction.delete(LogicalDatastoreType.OPERATIONAL, id);
+        LOG.debug("Deleting podnametouuid map for {}", podName);
+    }
+
+    public static InstanceIdentifier<Pods> getPodUUIDforPodName(String podName,
+                                            ReadTransaction readTransaction) throws ReadFailedException {
+        InstanceIdentifier<PodIdentifier> id = InstanceIdentifier.builder(PodidentifierInfo.class)
+                .child(PodIdentifier.class, new PodIdentifierKey(podName)).build();
+        InstanceIdentifier<?> instanceIdentifier = readTransaction.read(LogicalDatastoreType.OPERATIONAL, id)
+                .checkedGet().toJavaUtil().map(PodIdentifier::getPodUuid).orElse(null);
+        if (instanceIdentifier != null) {
+            return (InstanceIdentifier<Pods>) instanceIdentifier;
+        }
+        return null;
+    }
+
     public static void deleteElanInterface(String elanInterfaceName, WriteTransaction wrtConfigTxn) {
         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
                 .class, new ElanInterfaceKey(elanInterfaceName)).build();
@@ -147,13 +237,15 @@ public final class CoeUtils {
     }
 
     public static ElanInstance createElanInstanceForTheFirstPodInTheNetwork(String networkNS, String nodeIp,
-            org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.pod_attributes.Interface
-                    podInterface, ReadWriteTransaction tx) throws ReadFailedException {
+                                                 org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod
+                                                         .rev170611.pod_attributes.Interface podInterface,
+                                                 ReadWriteTransaction wrtConfigTxn) throws ReadFailedException {
         String elanInstanceName = buildElanInstanceName(nodeIp, networkNS);
         InstanceIdentifier<ElanInstance> id = createElanInstanceIdentifier(elanInstanceName);
-        Optional<ElanInstance> existingElanInstance = tx.read(LogicalDatastoreType.CONFIGURATION, id).checkedGet();
-        if (existingElanInstance.isPresent()) {
-            return existingElanInstance.get();
+        ElanInstance existingElanInstance = wrtConfigTxn.read(LogicalDatastoreType.CONFIGURATION, id)
+                .checkedGet().orNull();
+        if (existingElanInstance != null) {
+            return existingElanInstance;
         }
         Class<? extends SegmentTypeBase> segmentType = getSegmentTypeFromNetwork(podInterface);
         String segmentationId = String.valueOf(podInterface.getSegmentationId());
@@ -162,8 +254,178 @@ public final class CoeUtils {
         Boolean isExternal = false;
         ElanInstance elanInstance = CoeUtils.buildElanInstance(elanInstanceName, segmentType,
                 segmentationId, isExternal);
-        tx.put(LogicalDatastoreType.CONFIGURATION, id, elanInstance);
+        wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, id, elanInstance);
         LOG.info("ELAN instance created for the first pod in the network {}", podInterface.getUid());
         return elanInstance;
     }
+
+    public static Pair<String, String> getAttachedInterfaceAndMac(OvsdbTerminationPointAugmentation ovsdbTp) {
+        String interfaceName = null;
+        String macAddress = null;
+        if (ovsdbTp != null) {
+            List<InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
+            if (ifaceExtIds != null) {
+                Iterator var2 = ifaceExtIds.iterator();
+                while (var2.hasNext()) {
+                    if (interfaceName != null && macAddress != null) {
+                        break;
+                    }
+                    InterfaceExternalIds entry = (InterfaceExternalIds)var2.next();
+                    if (entry.getExternalIdKey().equals("iface-id")) {
+                        interfaceName = entry.getExternalIdValue();
+                        continue;
+                    }
+                    if (entry.getExternalIdKey().equals("attached-mac")) {
+                        macAddress = entry.getExternalIdValue();
+                        continue;
+                    }
+                }
+            }
+        }
+
+        return Pair.of(interfaceName, macAddress);
+    }
+
+    public static InstanceIdentifier<PodIdentifier> getPodMetaInstanceId(String externalInterfaceId) {
+        return InstanceIdentifier.builder(PodidentifierInfo.class)
+                .child(PodIdentifier.class, new PodIdentifierKey(externalInterfaceId)).build();
+    }
+
+    public static void createVpnInstance(String vpnName, List<String> rd, List<String> irt, List<String> ert,
+                                   VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion,
+                                   ReadWriteTransaction tx) throws ReadFailedException {
+        List<VpnTarget> vpnTargetList = new ArrayList<>();
+        LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
+
+        VpnInstanceBuilder builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName))
+                .setVpnInstanceName(vpnName)
+                .setType(type).setL3vni(l3vni);
+        if (irt != null && !irt.isEmpty()) {
+            if (ert != null && !ert.isEmpty()) {
+                List<String> commonRT = new ArrayList<>(irt);
+                commonRT.retainAll(ert);
+
+                for (String common : commonRT) {
+                    irt.remove(common);
+                    ert.remove(common);
+                    VpnTarget vpnTarget =
+                            new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
+                                    .setVrfRTType(VpnTarget.VrfRTType.Both).build();
+                    vpnTargetList.add(vpnTarget);
+                }
+            }
+            for (String importRT : irt) {
+                VpnTarget vpnTarget =
+                        new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
+                                .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
+                vpnTargetList.add(vpnTarget);
+            }
+        }
+
+        if (ert != null && !ert.isEmpty()) {
+            for (String exportRT : ert) {
+                VpnTarget vpnTarget =
+                        new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
+                                .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
+                vpnTargetList.add(vpnTarget);
+            }
+        }
+
+        VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
+
+        Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
+        Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
+
+        if (rd != null && !rd.isEmpty()) {
+            ipv4vpnBuilder.setRouteDistinguisher(rd);
+            ipv6vpnBuilder.setRouteDistinguisher(rd);
+        }
+
+        if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
+            builder.setIpv4Family(ipv4vpnBuilder.build());
+        }
+        if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
+            builder.setIpv6Family(ipv6vpnBuilder.build());
+        }
+        if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
+            builder.setIpv4Family(ipv4vpnBuilder.build());
+        }
+        VpnInstance newVpn = builder.build();
+        LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
+        InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
+                .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+        tx.put(LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
+    }
+
+    static void deleteVpnInstance(String vpnName, WriteTransaction wrtConfigTxn) {
+        LOG.debug("Deleting vpn-instance for {} ", vpnName);
+        InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
+                .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+        wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+    }
+
+    static InstanceIdentifier<VpnInterface> buildVpnInterfaceIdentifier(String ifName) {
+        InstanceIdentifier<VpnInterface> id = InstanceIdentifier.builder(VpnInterfaces.class).child(VpnInterface
+                .class, new VpnInterfaceKey(ifName)).build();
+        return id;
+    }
+
+    public static void createVpnInterface(String vpnName, Pods pod, String interfaceName, String macAddress,
+                                          boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
+        LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", interfaceName, isRouterInterface);
+        List<VpnInstanceNames> listVpn = new ArrayList<>();
+        listVpn.add(new VpnInstanceNamesBuilder().setKey(new VpnInstanceNamesKey(vpnName))
+                .setVpnName(vpnName).setAssociatedSubnetType(VpnInstanceNames.AssociatedSubnetType
+                        .V4Subnet).build());
+        VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(interfaceName))
+                .setName(interfaceName)
+                .setVpnInstanceNames(listVpn)
+                .setRouterInterface(isRouterInterface);
+        Adjacencies adjs = createPortIpAdjacencies(pod, interfaceName, macAddress, isRouterInterface);
+        if (adjs != null) {
+            vpnb.addAugmentation(Adjacencies.class, adjs);
+        }
+        VpnInterface vpnIf = vpnb.build();
+        LOG.info("Creating vpn interface {}", vpnIf);
+        InstanceIdentifier<VpnInterface> vpnIfIdentifier = buildVpnInterfaceIdentifier(interfaceName);
+        wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
+
+    }
+
+    public static void deleteVpnInterface(String interfaceName, WriteTransaction wrtConfigTxn) {
+        LOG.trace("deleteVpnInterface for Pod {}", interfaceName);
+        InstanceIdentifier<VpnInterface> vpnIfIdentifier = buildVpnInterfaceIdentifier(interfaceName);
+        wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
+    }
+
+    static Adjacencies createPortIpAdjacencies(Pods pod, String interfaceName, String macAddress,
+                                                  Boolean isRouterInterface) {
+        List<Adjacency> adjList = new ArrayList<>();
+        LOG.trace("create config adjacencies for Port: {}", interfaceName);
+        IpAddress ip = pod.getInterface().get(0).getIpAddress();
+        String ipValue = ip.getIpv4Address() != null ? ip.getIpv4Address().getValue() : ip.getIpv6Address().getValue();
+        String ipPrefix = ip.getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
+        String hostIp = new String(pod.getHostIpAddress().getValue());
+        UUID subnetId = UUID.nameUUIDFromBytes(hostIp.getBytes(StandardCharsets.UTF_8));
+        String gatewayIP = ipValue.replaceFirst("\\d+$", "1");
+        Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
+                .setMacAddress(macAddress).setAdjacencyType(Adjacency.AdjacencyType.PrimaryAdjacency)
+                .setSubnetId(new Uuid(subnetId.toString())).setSubnetGatewayIp(gatewayIP).build();
+        if (!adjList.contains(vmAdj)) {
+            adjList.add(vmAdj);
+        }
+
+        //if (isRouterInterface) {
+            // TODO
+            // create extraroute Adjacence for each ipValue,
+            // because router can have IPv4 and IPv6 subnet ports, or can have
+            // more that one IPv4 subnet port or more than one IPv6 subnet port
+            //List<Adjacency> erAdjList = getAdjacencyforExtraRoute(vpnId, routeList, ipValue);
+            //if (!erAdjList.isEmpty()) {
+            //    adjList.addAll(erAdjList);
+            //}
+        //}
+        return new AdjacenciesBuilder().setAdjacency(adjList).build();
+    }
+
 }
index 46570440f8107913bf6eb00a05bcba5a33c0babe..23ce7e5809adc04411769b87128e2c70d0a8bec0 100644 (file)
@@ -14,4 +14,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
                interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" />
     <reference id="jobCoordinator"
                interface="org.opendaylight.infrautils.jobcoordinator.JobCoordinator" />
+    <reference id="dataTreeEventCallbackRegistrar"
+               interface="org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar"/>
+    <reference id="cacheProvider"
+               interface="org.opendaylight.infrautils.caches.CacheProvider"/>
 </blueprint>
index d8757c6862f5f998dae9909d467c94ca93a62dd9..0307d1f8290457a3ae4b5c159acf54304e070f39 100644 (file)
@@ -44,6 +44,7 @@ module odl-l3vpn {
             leaf label { type uint32; config "false"; } /* optional */
             leaf mac_address {type string;} /* optional */
             leaf subnet_id {type yang:uuid;} /* optional */
+            leaf subnet_gateway_ip {type string;}  /* optional */
             leaf subnet_gateway_mac_address {type string; config "false";} /* optional */
             leaf vrf-id { type string; config "false"; }
             leaf phys-network-func {
index 7d7888e9340c8883f5f5ee525beb27f1e8954846..237b3a9906d92ad9f66971437c23fd3cc08dd9eb 100755 (executable)
@@ -36,6 +36,7 @@ import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -45,6 +46,7 @@ import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.NWUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.cache.DataObjectCache;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
@@ -111,7 +113,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.slf4j.Logger;
@@ -739,12 +740,13 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         List<Adjacency> value = new ArrayList<>();
         for (Adjacency nextHop : nextHops) {
             String rd = primaryRd;
-            Subnetmap sn = VpnUtil.getSubnetmapFromItsUuid(dataBroker, nextHop.getSubnetId());
-            if (!VpnUtil.isSubnetPartOfVpn(sn, vpnName)) {
+            String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
+            if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
+                    && NWUtil.isIpv4Address(nexthopIpValue)) {
                 String prefix = nextHop.getIpAddress() == null ?  "null" :
                       VpnUtil.getIpPrefix(nextHop.getIpAddress());
-                LOG.debug("processVpnInterfaceAdjacencies: Not Adding prefix {} to interface {}"
-                      + " as the subnet is not part of vpn {}", prefix, interfaceName, vpnName);
+                LOG.debug("processVpnInterfaceAdjacencies: UnsupportedOperation : Not Adding prefix {} to interface {}"
+                      + " as InternetVpn has an IPV4 address {}", prefix, interfaceName, vpnName);
                 continue;
             }
             if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
@@ -760,16 +762,24 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
                             prefixCue), true);
                 final Uuid subnetId = nextHop.getSubnetId();
-                final Optional<String> gatewayIp = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
-                if (gatewayIp.isPresent()) {
-                    gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp.get());
+
+                String gatewayIp = nextHop.getSubnetGatewayIp();
+                if (gatewayIp == null) {
+                    Optional<String> gatewayIpOptional = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
+                    if (gatewayIpOptional.isPresent()) {
+                        gatewayIp = gatewayIpOptional.get();
+                    }
+                }
+
+                if (gatewayIp != null) {
+                    gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp);
                     if (gwMac.isPresent()) {
                         // A valid mac-address is available for this subnet-gateway-ip
                         // Use this for programming ARP_RESPONDER table here.  And save this
                         // info into vpnInterface operational, so it can used in VrfEntryProcessor
                         // to populate L3_GW_MAC_TABLE there.
                         arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
-                                gatewayIp.get(), gwMac.get());
+                                gatewayIp, gwMac.get());
                         vpnInterfaceSubnetGwMacAddress = gwMac.get();
                     } else {
                         // A valid mac-address is not available for this subnet-gateway-ip
@@ -781,12 +791,12 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                             VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
                                     vpnId, writeInvTxn, NwConstants.ADD_FLOW, gwMac.get());
                             arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
-                                    gatewayIp.get(), gwMac.get());
+                                    gatewayIp, gwMac.get());
                         } else {
                             LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
                                 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
                                 + "gwIp {}",
-                                interfaceName, vpnName, gatewayIp.get());
+                                interfaceName, vpnName, gatewayIp);
                         }
                     }
                 } else {
@@ -1430,7 +1440,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
                     vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
         }
-        arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, subnetId);
+        arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
+                subnetId);
     }
 
     private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
index a426016d194181b2c767e9c26afe97e103fe689f..4bea1affb5a4aebead54491a14a77aae4b38becd 100644 (file)
@@ -101,15 +101,22 @@ public class ArpResponderHandler {
      *            lport tag of the interface
      * @param ifName
      *            interface to which ARP responder flow to be removed
+     * @param gatewayIp
+     *            subnet gateway ip
      * @param subnetUuid
      *            subnet Id of the interface
      */
-    public void removeArpResponderFlow(BigInteger dpId, int lportTag, String ifName,
+    public void removeArpResponderFlow(BigInteger dpId, int lportTag, String ifName, String gatewayIp,
             Uuid subnetUuid) {
-        Optional<String> gwIp = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetUuid);
-        if (gwIp.isPresent()) {
+        if (gatewayIp == null) {
+            Optional<String> gwIpOptional = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetUuid);
+            if (gwIpOptional.isPresent()) {
+                gatewayIp = gwIpOptional.get();
+            }
+        }
+        if (gatewayIp != null) {
             ArpReponderInputBuilder builder = new ArpReponderInputBuilder();
-            builder.setDpId(dpId).setInterfaceName(ifName).setSpa(gwIp.get()).setLportTag(lportTag);
+            builder.setDpId(dpId).setInterfaceName(ifName).setSpa(gatewayIp).setLportTag(lportTag);
             elanService.removeArpResponderFlow(builder.buildForRemoveFlow());
         }
     }