Merge "BUG 4978 add neutron service to feature openstack"
authorVishal Thapar <vishal.thapar@ericsson.com>
Wed, 27 Jan 2016 07:19:14 +0000 (07:19 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 27 Jan 2016 07:19:14 +0000 (07:19 +0000)
77 files changed:
alivenessmonitor/alivenessmonitor-api/src/main/yang/aliveness-monitor.yang
commons/binding-parent/pom.xml
commons/config-parent/pom.xml
distribution/karaf/pom.xml
features/pom.xml
features/src/main/features/features.xml
fibmanager/fibmanager-api/src/main/yang/odl-fib.yang
fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/FibManager.java
fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/FibUtil.java [new file with mode: 0644]
fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/NexthopManager.java
fibmanager/fibmanager-impl/src/test/java/org/opendaylight/vpnservice/fibmanager/test/FibManagerTest.java
interfacemgr/interfacemgr-api/src/main/yang/odl-interface-meta.yang
interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang
interfacemgr/interfacemgr-impl/pom.xml
interfacemgr/interfacemgr-impl/src/main/config/default-config.xml
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/AlivenessMonitorUtils.java [new file with mode: 0644]
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/InterfaceManagerCommonUtils.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/InterfaceMetaUtils.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/listeners/AlivenessMonitorListener.java [new file with mode: 0644]
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/listeners/InterfaceConfigListener.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/listeners/InterfaceInventoryStateListener.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/listeners/VlanMemberConfigListener.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigAddHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigRemoveHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigUpdateHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigUpdateHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateAddHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateRemoveHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateUpdateHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceTopologyStateAddHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceTopologyStateRemoveHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/utilities/SouthboundUtils.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/interfacemgr/impl/rev150325/InterfacemgrImplModule.java
interfacemgr/interfacemgr-impl/src/main/yang/interfacemgr-impl.yang
interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/StateInterfaceTest.java
interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/TunnelInterfaceConfigurationTest.java
interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/VlanInterfaceConfigurationTest.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/interfaces/IMdsalApiManager.java
mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java
model-bgp/src/main/yang/bgp.yang
model-bgp/src/main/yang/ebgp.yang
neutronvpn/neutronvpn-api/pom.xml
neutronvpn/neutronvpn-impl/pom.xml
neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronNetworkChangeListener.java
neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronPortChangeListener.java
neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronRouterChangeListener.java
neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnManager.java
neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnUtils.java
pom.xml
vpnintent/api/pom.xml [new file with mode: 0644]
vpnintent/api/src/main/yang/vpnintent.yang [new file with mode: 0644]
vpnintent/impl/pom.xml [new file with mode: 0644]
vpnintent/impl/src/main/config/default-config.xml [new file with mode: 0644]
vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java [new file with mode: 0644]
vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MappingServiceManager.java [new file with mode: 0644]
vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MplsLabelManagerService.java [new file with mode: 0644]
vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/VpnintentProvider.java [new file with mode: 0644]
vpnintent/impl/src/main/java/org/opendaylight/vpnservice/utils/IidFactory.java [new file with mode: 0644]
vpnintent/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpnintent/impl/rev141210/VpnintentImplModule.java [new file with mode: 0644]
vpnintent/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpnintent/impl/rev141210/VpnintentImplModuleFactory.java [new file with mode: 0644]
vpnintent/impl/src/main/yang/vpnintent-impl.yang [new file with mode: 0644]
vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/IntentServiceManagerTest.java [new file with mode: 0644]
vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/MappingServiceManagerTests.java [new file with mode: 0644]
vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/VpnintentProviderTest.java [new file with mode: 0644]
vpnintent/pom.xml [new file with mode: 0644]
vpnintent/resources/vpnintent.postman_collection [new file with mode: 0644]
vpnmanager/vpnmanager-api/src/main/yang/odl-l3vpn.yang
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/InterfaceStateChangeListener.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnConstants.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnManager.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnNotifyTask.java [new file with mode: 0644]
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnUtil.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnserviceProvider.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/utilities/InterfaceUtils.java

index a9828107fc4971d4e3ddc1933eff78b7f2d210e6..134288f6542e598977e164edf30d248c4c28f71e 100644 (file)
@@ -4,6 +4,7 @@ module aliveness-monitor {
 
     import ietf-inet-types {
         prefix inet;
+        revision-date "2010-09-24";
     }
 
     revision "2015-06-29" {
index 6ed9de4bce1987ad130ed37b347809711f059684..1ba8e773697bb65e799a37ae7fd8e6eae9cf857c 100644 (file)
@@ -27,7 +27,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <ietf.interfaces.version>2014.05.08.9-SNAPSHOT</ietf.interfaces.version>
     <iana.if.type.version>2014.05.08.9-SNAPSHOT</iana.if.type.version>
     <yang.ext.version>2013.09.07.9-SNAPSHOT</yang.ext.version>
-    <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+    <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
     <mdsal.version>2.1.0-SNAPSHOT</mdsal.version>
     <controller.mdsal.version>1.4.0-SNAPSHOT</controller.mdsal.version>
     <vpns.mdsalutil.version>0.3.0-SNAPSHOT</vpns.mdsalutil.version>
index 7f7abaee1cbefc4cae236fa5667d968c968106d9..dae5ca5efea9dabf37b17f4b94474395316028ab 100644 (file)
@@ -24,7 +24,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <properties>
     <!-- ODL -->
     <vpnservices.version>0.3.0-SNAPSHOT</vpnservices.version>
-    <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+    <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
+    <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
     <controller.mdsal.version>1.4.0-SNAPSHOT</controller.mdsal.version>
     <vpns.mdsalutil.version>0.3.0-SNAPSHOT</vpns.mdsalutil.version>
     <model.bgp.version>2013.07.15.9-SNAPSHOT</model.bgp.version>
@@ -47,7 +48,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <dependency>
         <groupId>org.opendaylight.mdsal.model</groupId>
         <artifactId>mdsal-model-artifacts</artifactId>
-        <version>0.9.0-SNAPSHOT</version>
+        <version>${mdsal.model.version}</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
index 3fdedb91c89add5a09e6368134ee012eaa840a1b..c6f059b9e1abee90346f626960b9fe6d4d8d6459 100644 (file)
@@ -22,7 +22,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <maven>3.1.1</maven>
   </prerequisites>
   <properties>
-    <karaf.localFeature>odl-vpnservice-core</karaf.localFeature>
+    <!-- <karaf.localFeature>odl-vpnservice-core</karaf.localFeature> -->
   </properties>
   <dependencyManagement>
     <dependencies>
index 536106a1b8726079a0b44dabf80caade5a70b8ec..2508f3ce053097137e5c51e81248524fed0a165a 100644 (file)
@@ -24,12 +24,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <mdsal.version>1.4.0-SNAPSHOT</mdsal.version>
     <openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
     <restconf.version>1.4.0-SNAPSHOT</restconf.version>
-    <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+    <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
     <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
     <vpnservices.version>0.3.0-SNAPSHOT</vpnservices.version>
     <ovsdb.version>1.3.0-SNAPSHOT</ovsdb.version>
     <liblldp.version>0.11.0-SNAPSHOT</liblldp.version>
     <neutron.version>0.7.0-SNAPSHOT</neutron.version>
+    <nic.version>1.2.0-SNAPSHOT</nic.version>
     <arputil.version>${vpnservices.version}</arputil.version>
     <mdsalutil.version>${vpnservices.version}</mdsalutil.version>
     <vpnmanager.version>${vpnservices.version}</vpnmanager.version>
@@ -86,6 +87,14 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <type>xml</type>
       <scope>runtime</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.nic</groupId>
+      <artifactId>features-nic</artifactId>
+      <classifier>features</classifier>
+      <version>${nic.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.ovsdb</groupId>
       <artifactId>features-ovsdb</artifactId>
@@ -377,5 +386,22 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <artifactId>commons-net</artifactId>
       <version>${commons.net.version}</version>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vpnintent-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vpnintent-impl</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vpnintent-impl</artifactId>
+      <version>${vpnservices.version}</version>
+      <classifier>config</classifier>
+      <type>xml</type>
+    </dependency>
   </dependencies>
 </project>
index 3b5ab6a2b2cec959a6be44d76924455c687496c2..a96363e54ac77f6b2dd087e8f07a63779311a8b8 100644 (file)
@@ -18,6 +18,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.ovsdb/features-ovsdb/${ovsdb.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.neutron/features-neutron/${neutron.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.nic/features-nic/{{VERSION}}/xml/features</repository>
   <feature name='odl-vpnservice-api' version='${project.version}' description='OpenDaylight :: vpnservice :: api '>
     <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
     <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
@@ -103,4 +104,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <bundle>mvn:org.opendaylight.neutron/dummyprovider/${neutron.version}</bundle>
     <feature version="${project.version}">odl-vpnservice-impl-rest</feature>
   </feature>
+  <feature name='odl-vpnservice-intent' version='${project.version}' description='OpenDaylight :: vpnservice :: intent'>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version='${nic.version}'>odl-nic-core-service-mdsal</feature>
+    <feature version='${nic.version}'>odl-nic-core</feature>
+    <feature version='${nic.version}'>odl-nic-listeners</feature>
+    <bundle>mvn:org.opendaylight.vpnservice/vpnintent-api/{{VERSION}}</bundle>
+    <bundle>mvn:org.opendaylight.vpnservice/vpnintent-impl/{{VERSION}}</bundle>
+    <configfile finalname="vpnintent-impl-default-config.xml">mvn:org.opendaylight.vpnservice/vpnintent-impl/{{VERSION}}/xml/config</configfile>
+  </feature>
   </features>
index bea6c951615dc786d4fe01ebd202407b43d63dad..046855e323edba431836914bbdf25bdf85a1872b 100644 (file)
@@ -32,7 +32,7 @@ module odl-fib {
     }
 
     container fibEntries {
-        config false;
+        config true;
         list vrfTables{
             key "routeDistinguisher";
             leaf routeDistinguisher {type string;}
index 0135f1d10b2f3e7231add2b840497a7de0205b67..80500315315a38b9a18cd35d8a9d87daeb78c56e 100644 (file)
@@ -43,6 +43,7 @@ import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnToExtraroute;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
@@ -52,6 +53,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instanc
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
@@ -64,6 +70,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpc
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetTunnelTypeOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -90,17 +99,6 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   public static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
 
 
-  private static final FutureCallback<Void> DEFAULT_CALLBACK =
-      new FutureCallback<Void>() {
-        public void onSuccess(Void result) {
-          LOG.debug("Success in Datastore write operation");
-        }
-
-        public void onFailure(Throwable error) {
-          LOG.error("Error in Datastore write operation", error);
-        };
-      };
-
   public FibManager(final DataBroker db) {
     super(VrfEntry.class);
     broker = db;
@@ -142,7 +140,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
   private void registerListener(final DataBroker db) {
     try {
-      listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+      listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
                                                            getWildCardPath(), FibManager.this, DataChangeScope.SUBTREE);
     } catch (final Exception e) {
       LOG.error("FibManager DataChange listener registration fail!", e);
@@ -150,31 +148,11 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     }
   }
 
-  private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
-                                                  InstanceIdentifier<T> path) {
-
-    ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
-
-    Optional<T> result = Optional.absent();
-    try {
-      result = tx.read(datastoreType, path).get();
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-
-    return result;
-  }
 
   private InstanceIdentifier<VrfEntry> getWildCardPath() {
     return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class).child(VrfEntry.class);
   }
 
-  private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
-                                                 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
-    WriteTransaction tx = broker.newWriteOnlyTransaction();
-    tx.put(datastoreType, path, data, true);
-    Futures.addCallback(tx.submit(), callback);
-  }
 
   @Override
   protected void add(final InstanceIdentifier<VrfEntry> identifier,
@@ -221,18 +199,20 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   public BigInteger createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
     BigInteger localDpnId = BigInteger.ZERO;
     Prefixes localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
-    boolean staticRoute = false;
+    String localNextHopIP = vrfEntry.getDestPrefix();
 
-    //If the vrf entry is a static/extra route, the nexthop of the entry would be a adjacency in the vpn
     if(localNextHopInfo == null) {
-      localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getNextHopAddress() + "/32");
-      staticRoute = true;
+        //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
+        Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+        if (extra_route != null) {
+            localNextHopInfo = getPrefixToInterface(vpnId, extra_route.getNexthopIp() + "/32");
+            localNextHopIP = extra_route.getNexthopIp() + "/32";
+        }
     }
 
     if(localNextHopInfo != null) {
       localDpnId = localNextHopInfo.getDpnId();
-      long groupId = nextHopManager.createLocalNextHop(vpnId, localDpnId, localNextHopInfo.getVpnInterfaceName(),
-                                                        (staticRoute == true) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix());
+      long groupId = nextHopManager.createLocalNextHop(vpnId, localDpnId, localNextHopInfo.getVpnInterfaceName(), localNextHopIP);
       List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
 
       actionInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
@@ -296,23 +276,28 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   public BigInteger deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
     BigInteger localDpnId = BigInteger.ZERO;
     VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
-    boolean staticRoute = false;
+    String localNextHopIP = vrfEntry.getDestPrefix();
 
-    //If the vrf entry is a static/extra route, the nexthop of the entry would be a adjacency in the vpn
     if(localNextHopInfo == null) {
-      localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getNextHopAddress() + "/32");
-      staticRoute = true;
+        //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
+        Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+        if (extra_route != null) {
+            localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp());
+            localNextHopIP = extra_route.getNexthopIp() + "/32";
+        }
     }
 
+
     if(localNextHopInfo != null) {
       localDpnId = localNextHopInfo.getDpnId();
-      if (getPrefixToInterface(vpnId, (staticRoute == true) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix()) == null) {
+      //if (getPrefixToInterface(vpnId, (staticRoute == true) ? extra_route.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix()) == null)
+      {
         makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, null /* invalid */,
                            NwConstants.DEL_FLOW);
         makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), 0 /* invalid */,
                            vrfEntry.getNextHopAddress(), NwConstants.DEL_FLOW);
         removeTunnelTableEntry(localDpnId, vrfEntry.getLabel());
-        deleteLocalAdjacency(localDpnId, vpnId, (staticRoute == true) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix());
+        deleteLocalAdjacency(localDpnId, vpnId, localNextHopIP);
       }
     }
     return localDpnId;
@@ -325,10 +310,22 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
   private Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
     Optional<Prefixes> localNextHopInfoData =
-        read(LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
+        FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
     return  localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
   }
-  
+
+    private InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
+        return InstanceIdentifier.builder(VpnToExtraroute.class)
+                .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
+                        new ExtrarouteKey(ipPrefix)).build();
+    }
+
+    private Extraroute getVpnToExtraroute(String rd, String ipPrefix) {
+        Optional<Extraroute> extraRouteInfo =
+                FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, getVpnToExtrarouteIdentifier(rd, ipPrefix));
+        return  extraRouteInfo.isPresent() ? extraRouteInfo.get() : null;
+
+    }
 
   private Class<? extends TunnelTypeBase> getTunnelType(String ifName) {
         try {
@@ -354,7 +351,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     String rd = vrfTableKey.getRouteDistinguisher();
     LOG.debug("adding route " + vrfEntry.getDestPrefix() + " " + rd);
     /********************************************/
-    String tunnelInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+    String tunnelInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry, rd);
     if(tunnelInterface == null) {
       LOG.error("Could not get interface for nexthop: {} in vpn {}",
                                    vrfEntry.getNextHopAddress(), rd);
@@ -414,6 +411,67 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
         "Successfully added fib entry for " + vrfEntry.getDestPrefix() + " vpnId " + vpnId);
   }
 
+    private void delIntfFromDpnToVpnList(long vpnId, BigInteger dpnId, String intfName, String rd) {
+        InstanceIdentifier<VpnToDpnList> id = FibUtil.getVpnToDpnListIdentifier(rd, dpnId);
+        Optional<VpnToDpnList> dpnInVpn = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+        if (dpnInVpn.isPresent()) {
+            List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+                    .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
+            org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+                    currVpnInterface = new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+            if (vpnInterfaces.remove(currVpnInterface)) {
+                if (vpnInterfaces.isEmpty()) {
+                    //FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id);
+                    cleanUpDpnForVpn(dpnId, vpnId, rd);
+                } else {
+                    FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+                            org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+                                    .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+                            new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(intfName)));
+                }
+            }
+        }
+    }
+
+  private void cleanUpOpDataForFib(Long vpnId, String rd, final VrfEntry vrfEntry) {
+    /* Get interface info from prefix to interface mapping;
+        Use the interface info to get the corresponding vpn interface op DS entry,
+        remove the adjacency corresponding to this fib entry.
+        If adjacency removed is the last adjacency, clean up the following:
+         - vpn interface from dpntovpn list, dpn if last vpn interface on dpn
+         - prefix to interface entry
+         - vpn interface op DS
+     */
+      Prefixes prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
+      boolean extra_route = false;
+      if (prefixInfo == null) {
+          prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getNextHopAddress() + "/32");
+          extra_route = true;
+      }
+      if (prefixInfo == null)
+          return; //Don't have any info for this prefix (shouldn't happen); need to return
+      String ifName = prefixInfo.getVpnInterfaceName();
+      Optional<Adjacencies> optAdjacencies = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjListPath(ifName));
+      int numAdj = 0;
+      if (optAdjacencies.isPresent()) {
+          numAdj = optAdjacencies.get().getAdjacency().size();
+      }
+      //remove adjacency corr to prefix
+      FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
+
+      if((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
+        //clean up the vpn interface from DpnToVpn list
+          delIntfFromDpnToVpnList(vpnId, prefixInfo.getDpnId(), ifName, rd);
+          FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+                  FibUtil.getPrefixToInterfaceIdentifier(
+                          vpnId,
+                          (extra_route) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix()));
+          FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+                  FibUtil.getVpnInterfaceIdentifier(ifName));
+      }
+  }
+
   private void deleteFibEntries(final InstanceIdentifier<VrfEntry> identifier,
                                 final VrfEntry vrfEntry) {
     final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
@@ -431,8 +489,10 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
           deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry);
         }
       }
-
     }
+    //The flow/group entry has been deleted from config DS; need to clean up associated operational
+    //DS entries in VPN Op DS, VpnInstanceOpData and PrefixToInterface to complete deletion
+    cleanUpOpDataForFib(vpnInstance.getVpnId(), vrfTableKey.getRouteDistinguisher(), vrfEntry);
   }
 
   public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
@@ -440,7 +500,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                                 final VrfEntry vrfEntry) {
     LOG.debug("deleting route "+ vrfEntry.getDestPrefix() + " "+vpnId);
     String rd = vrfTableKey.getRouteDistinguisher();
-    String egressInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+    String egressInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry, rd);
     if(egressInterface == null) {
       LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
                 vrfEntry.getNextHopAddress(), rd);
@@ -506,13 +566,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
       * for or for notification that operational DS write for flows is done. We do not turn on the stats writing for flows,
       * so that notification never comes, so we do not need that wait. Sending the lowest value of wait "1 ms" since 0 wait means
       * wait indefinitely. */
-      // FIXME: sync calls.
-      //mdsalManager.syncInstallFlow(flowEntity, 1);
-      mdsalManager.installFlow(flowEntity);
+      mdsalManager.syncInstallFlow(flowEntity, 1);
     } else {
-      // FIXME: sync calls.
-      // mdsalManager.syncRemoveFlow(flowEntity, 1);
-      mdsalManager.removeFlow(flowEntity);
+      mdsalManager.syncRemoveFlow(flowEntity, 1);
     }
   }
 
@@ -544,13 +600,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
       * so that notification never comes, so we do not need that wait. Sending the lowest value of wait "1 ms" since 0 wait means
       * wait indefinitely. */
 
-      // FIXME:
-      // mdsalManager.syncInstallFlow(flowEntity, 1);
-      mdsalManager.installFlow(flowEntity);
+      mdsalManager.syncInstallFlow(flowEntity, 1);
     } else {
-      // FIXME:
-      // mdsalManager.syncRemoveFlow(flowEntity, 1);
-      mdsalManager.removeFlow(flowEntity);
+      mdsalManager.syncRemoveFlow(flowEntity, 1);
     }
     LOG.debug("LFIB Entry for dpID {} : label : {} group {} modified successfully {}",dpId, label, groupId );
   }
@@ -567,7 +619,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   public void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd) {
     LOG.trace("New dpn {} for vpn {} : populateFibOnNewDpn", dpnId, rd);
     InstanceIdentifier<VrfTables> id = buildVrfId(rd);
-    Optional<VrfTables> vrfTable = read(LogicalDatastoreType.OPERATIONAL, id);
+    Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
     if(vrfTable.isPresent()) {
       for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
         // Passing null as we don't know the dpn
@@ -580,7 +632,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd) {
     LOG.trace("Remove dpn {} for vpn {} : cleanUpDpnForVpn", dpnId, rd);
     InstanceIdentifier<VrfTables> id = buildVrfId(rd);
-    Optional<VrfTables> vrfTable = read(LogicalDatastoreType.OPERATIONAL, id);
+    Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
     if(vrfTable.isPresent()) {
       for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
         // Passing null as we don't know the dpn
@@ -612,14 +664,20 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   }
 
   protected String resolveAdjacency(final BigInteger localDpnId, final BigInteger remoteDpnId,
-                                              final long vpnId, final VrfEntry vrfEntry) {
+                                              final long vpnId, final VrfEntry vrfEntry, String rd) {
     String adjacency = null;
-    LOG.trace("resolveAdjacency called with localdpid{} remotedpid {}, vpnId{}, VrfEntry {}", localDpnId, remoteDpnId, vpnId, vrfEntry);;
+    boolean staticRoute = false;
+    LOG.trace("resolveAdjacency called with localdpid{} remotedpid {}, vpnId{}, VrfEntry {}", localDpnId, remoteDpnId, vpnId, vrfEntry);
     try {
-      adjacency =
+        Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+        if(extra_route != null) {
+            staticRoute = true;
+        }
+
+        adjacency =
           nextHopManager.getRemoteNextHopPointer(localDpnId, remoteDpnId, vpnId,
                                                  vrfEntry.getDestPrefix(),
-                                                 vrfEntry.getNextHopAddress());
+                  (staticRoute == true) ? extra_route.getNexthopIp() : vrfEntry.getNextHopAddress());
     } catch (NullPointerException e) {
       LOG.trace("", e);
     }
@@ -629,7 +687,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   protected VpnInstanceOpDataEntry getVpnInstance(String rd) {
     InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.create(VpnInstanceOpData.class).child(
         VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd));
-    Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(LogicalDatastoreType.OPERATIONAL, id);
+    Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
     if(vpnInstanceOpData.isPresent()) {
       return vpnInstanceOpData.get();
     }
@@ -707,7 +765,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     result.add(String.format("   %-7s  %-20s  %-20s  %-7s", "RD", "Prefix", "Nexthop", "Label"));
     result.add("-------------------------------------------------------------------");
     InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
-    Optional<FibEntries> fibEntries = read(LogicalDatastoreType.OPERATIONAL, id);
+    Optional<FibEntries> fibEntries = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
     if (fibEntries.isPresent()) {
       List<VrfTables> vrfTables = fibEntries.get().getVrfTables();
       for (VrfTables vrfTable : vrfTables) {
diff --git a/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/FibUtil.java b/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/FibUtil.java
new file mode 100644 (file)
index 0000000..273d648
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016 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.vpnservice.fibmanager;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+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.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+
+public class FibUtil {
+    private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
+    static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
+                                                   InstanceIdentifier<T> path) {
+
+        ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+        Optional<T> result = Optional.absent();
+        try {
+            result = tx.read(datastoreType, path).get();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        return result;
+    }
+
+    static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+                                                  InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.merge(datastoreType, path, data, true);
+        Futures.addCallback(tx.submit(), callback);
+    }
+
+    static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+                                                 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.merge(datastoreType, path, data, true);
+        tx.submit();
+    }
+
+    static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.delete(datastoreType, path);
+        Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
+    }
+
+    static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
+        return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+                .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).augmentation(
+                        org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey(ipAddress)).build();
+    }
+
+    static InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
+        return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+                .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).augmentation(
+                        org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies.class).build();
+    }
+
+    static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
+        return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey(vpnId)).child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes.class,
+                        new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
+    }
+
+    static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
+        return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+                .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).build();
+    }
+
+    static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
+        return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey(rd))
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey(dpnId)).build();
+    }
+
+    static final FutureCallback<Void> DEFAULT_CALLBACK =
+            new FutureCallback<Void>() {
+                public void onSuccess(Void result) {
+                    LOG.debug("Success in Datastore operation");
+                }
+
+                public void onFailure(Throwable error) {
+                    LOG.error("Error in Datastore operation", error);
+                };
+            };
+
+}
index 83c6feb93a176d51d3c757b9496ab8ea9632e893..a3cd7c4eea9af109c9fde30e87a205b3441bbad3 100644 (file)
@@ -83,6 +83,7 @@ public class NexthopManager implements AutoCloseable {
     private static final short FIB_TABLE = 21;
     private static final short DEFAULT_FLOW_PRIORITY = 10;
     private static final String NEXTHOP_ID_POOL_NAME = "nextHopPointerPool";
+    private static final long FIXED_DELAY_IN_MILLISECONDS = 4000;
 
     private static final FutureCallback<Void> DEFAULT_CALLBACK =
         new FutureCallback<Void>() {
@@ -285,8 +286,7 @@ public class NexthopManager implements AutoCloseable {
                 addVpnNexthopToDS(dpnId, vpnId, ipAddress, groupId);
 
                 // install Group
-                // FIXME: mdsalManager.syncInstallGroup(groupEntity);
-                mdsalManager.installGroup(groupEntity);
+                mdsalManager.syncInstallGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS);
 
             } else {
                 //nexthop exists already; a new flow is going to point to it, increment the flowrefCount by 1
@@ -362,11 +362,13 @@ public class NexthopManager implements AutoCloseable {
                   localDpnId, remoteDpnId, vpnId, prefixIp, nextHopIp);
 
         LOG.trace("getRemoteNextHopPointer: Calling ITM with localDpnId {} ", localDpnId);
-        try{
-            // here use the config for tunnel type param
-            tunnelIfName = getTunnelInterfaceName(remoteDpnId, IpAddressBuilder.getDefaultInstance(nextHopIp));
-        }catch(Exception ex){
-            LOG.error("Error while retrieving nexthop pointer for DC Gateway : ", ex.getMessage());
+        if (nextHopIp != null && !nextHopIp.isEmpty()) {
+            try{
+                // here use the config for tunnel type param
+                tunnelIfName = getTunnelInterfaceName(remoteDpnId, IpAddressBuilder.getDefaultInstance(nextHopIp));
+            }catch(Exception ex){
+            LOG.error("Error while retrieving nexthop pointer for nexthop {} : ", nextHopIp, ex.getMessage());
+            }
         }
         return tunnelIfName;
     }
@@ -401,8 +403,7 @@ public class NexthopManager implements AutoCloseable {
                     GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
                             dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
                     // remove Group ...
-                    // FIXME: mdsalManager.syncRemoveGroup(groupEntity);
-                    mdsalManager.removeGroup(groupEntity);
+                    mdsalManager.syncRemoveGroup(groupEntity);
                     //update MD-SAL DS
                     removeVpnNexthopFromDS(vpnId, ipAddress);
                     //release groupId
@@ -463,4 +464,10 @@ public class NexthopManager implements AutoCloseable {
             .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
                 Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
     }
+
+    InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
+        return InstanceIdentifier.builder(VpnInterfaces.class)
+                .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
+                        Adjacencies.class).build();
+    }
 }
index f68a5f5f145c31baf80397af0555906eef2fca62..89841010dd808e0e5c56ed614e4257738f51a102 100644 (file)
@@ -77,6 +77,7 @@ public class FibManagerTest {
   private static final int label = 10;
   BigInteger Dpn;
   private static final long vpnId = 101L;
+  private static final long vpnIntfCnt = 2;
 
   private void SetupMocks() {
     Dpn = BigInteger.valueOf(100000L);
@@ -115,6 +116,9 @@ public class FibManagerTest {
             return testRd;
           }
 
+          @Override
+          public Long getVpnInterfaceCount() { return vpnIntfCnt; }
+
           @Override
           public List<VpnToDpnList> getVpnToDpnList() {
             List <VpnToDpnList> vpnToDpnLists =  new ArrayList<>();
index ef6aa20aeef774d4325f6e6dfc5078a47bb4e9c1..8654cc8f12c9851ee17f4f639cbabb90d17b07e6 100644 (file)
@@ -73,5 +73,31 @@ module odl-interface-meta {
                    type string;
                }
            }
+   }
+
+   container interface-monitor-id-map {
+       config false;
+       list interface-monitor-id {
+           key interface-name;
+           leaf interface-name {
+               type string;
+           }
+           leaf-list monitor-id {
+               type uint32;
+           }
+       }
+   }
+
+   container monitor-id-interface-map {
+       config false;
+       list monitor-id-interface {
+           key monitor-id;
+           leaf monitor-id {
+               type uint32;
+           }
+           leaf interface-name {
+               type string;
+           }
        }
+   }
 }
\ No newline at end of file
index db04860f8f96f568d3d9a0a0d8fd1b21382c2edc..29994dafdc8937b8f29842a81f3e1f3595ae018b 100644 (file)
@@ -188,6 +188,16 @@ module odl-interface {
             type inet:ip-address;
             description "gateway IP address";
         }
+
+        leaf monitor-enabled {
+            type boolean;
+            default false;
+        }
+
+        leaf monitor-interval {
+             type uint32;
+              default 10000;
+        }
     }
 
     augment "/if:interfaces/if:interface" {
@@ -216,6 +226,7 @@ module odl-interface {
             description "gateway IP address";
         }
     }
+
     /* MPLS logical port */
     augment "/if:interfaces/if:interface" {
         ext:augment-identifier "if-mpls";
index 73d14d38aa9b6dc1b42871eb7cb0cc503a29e8b9..7580d63fd254679733cabb86cd889e5402e3d790 100644 (file)
@@ -55,10 +55,19 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>idmanager-impl</artifactId>
       <version>${vpnservices.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.vpnservice</groupId>
+      <artifactId>alivenessmonitor-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.ovsdb</groupId>
       <artifactId>southbound-api</artifactId>
       <version>${vpns.ovsdb.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+    </dependency>
   </dependencies>
 </project>
index a7b9952a34d51d38ace63cf50fe1afb295ec68da..8eff6555a333c3c72e0cbae36d451a47a03461c2 100644 (file)
@@ -13,6 +13,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <capability>urn:opendaylight:params:xml:ns:yang:interfacemgr:impl?module=interfacemgr-impl&amp;revision=2015-03-25</capability>
       <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&amp;revision=2015-04-10</capability>
       <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28</capability>
   </required-capabilities>
   <configuration>
 
@@ -29,6 +30,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
             <name>mdsalutil-service</name>
           </mdsalutil>
+          <notification-service>
+            <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-service</type>
+            <name>binding-notification-adapter</name>
+          </notification-service>
           <rpc-registry>
             <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
             <name>binding-rpc-broker</name>
index adebb5fa07010351bc0468af30fdd7de3a93e17f..eacf25cab94ba7fa55c8046a33c3670c2b6d1038 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
 import org.opendaylight.vpnservice.interfacemgr.globals.VlanInterfaceInfo;
 import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
 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.iana._if.type.rev140508.Tunnel;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
@@ -36,6 +37,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeGre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.ProfileBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
@@ -45,6 +48,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.InterfaceMonitorIdMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.MonitorIdInterfaceMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan.L2vlanMode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
@@ -273,7 +284,4 @@ public class IfmUtil {
         }
         return vlanInterfaceInfo;
     }
-
-
-
 }
index f1a9c84963399a5f4974a42c3dd7ad6f75c591d7..b06fd247e059122dd45af2e1a928c9c0db0d14e4 100644 (file)
@@ -13,6 +13,8 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
@@ -36,9 +38,11 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 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.interfaces.rev140508.interfaces.state.Interface.OperStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;
@@ -59,6 +63,8 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable
 
     private RpcProviderRegistry rpcProviderRegistry;
     private IdManagerService idManager;
+    private NotificationService notificationService;
+    private AlivenessMonitorService alivenessManager;
     private IMdsalApiManager mdsalManager;
     private InterfaceConfigListener interfaceConfigListener;
     private InterfaceTopologyStateListener topologyStateListener;
@@ -66,6 +72,7 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable
     private FlowBasedServicesInterfaceStateListener flowBasedServicesInterfaceStateListener;
     private FlowBasedServicesConfigListener flowBasedServicesConfigListener;
     private VlanMemberConfigListener vlanMemberConfigListener;
+    private org.opendaylight.vpnservice.interfacemgr.listeners.AlivenessMonitorListener alivenessMonitorListener;
     private DataBroker dataBroker;
     private InterfaceManagerRpcService interfaceManagerRpcService;
     private BindingAwareBroker.RpcRegistration<OdlInterfaceRpcService> rpcRegistration;
@@ -78,6 +85,10 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable
         this.mdsalManager = mdsalManager;
     }
 
+    public void setNotificationService(NotificationService notificationService) {
+        this.notificationService = notificationService;
+    }
+
     @Override
     public void onSessionInitiated(ProviderContext session) {
         LOG.info("InterfacemgrProvider Session Initiated");
@@ -86,14 +97,15 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable
             idManager = rpcProviderRegistry.getRpcService(IdManagerService.class);
             createIdPool();
 
+            alivenessManager = rpcProviderRegistry.getRpcService(AlivenessMonitorService.class);
             interfaceManagerRpcService = new InterfaceManagerRpcService(dataBroker, mdsalManager);
             rpcRegistration = getRpcProviderRegistry().addRpcImplementation(
                     OdlInterfaceRpcService.class, interfaceManagerRpcService);
 
-            interfaceConfigListener = new InterfaceConfigListener(dataBroker, idManager);
+            interfaceConfigListener = new InterfaceConfigListener(dataBroker, idManager,alivenessManager, mdsalManager);
             interfaceConfigListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
 
-            interfaceInventoryStateListener = new InterfaceInventoryStateListener(dataBroker, idManager, mdsalManager);
+            interfaceInventoryStateListener = new InterfaceInventoryStateListener(dataBroker, idManager, mdsalManager, alivenessManager);
             interfaceInventoryStateListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
 
             topologyStateListener = new InterfaceTopologyStateListener(dataBroker);
@@ -107,8 +119,10 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable
             flowBasedServicesInterfaceStateListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
 
             vlanMemberConfigListener =
-                               new VlanMemberConfigListener(dataBroker, idManager);
+                               new VlanMemberConfigListener(dataBroker, idManager, alivenessManager,mdsalManager);
             vlanMemberConfigListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+            alivenessMonitorListener = new org.opendaylight.vpnservice.interfacemgr.listeners.AlivenessMonitorListener(dataBroker);
+            notificationService.registerNotificationListener(alivenessMonitorListener);
         } catch (Exception e) {
             LOG.error("Error initializing services", e);
         }
diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/AlivenessMonitorUtils.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/AlivenessMonitorUtils.java
new file mode 100644 (file)
index 0000000..598a4bc
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2015 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.vpnservice.interfacemgr.commons;
+
+import com.google.common.base.Optional;
+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;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
+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.vpnservice.alivenessmonitor.rev150629.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.ProfileBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class AlivenessMonitorUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorUtils.class);
+    private static final int FAILURE_THRESHOLD = 4;
+    private static final int MONITORING_INTERVAL = 10;
+    private static final int MONITORING_WINDOW = 4;
+
+    public static void startLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+                                            Interface trunkInterface) {
+        //LLDP monitoring for the trunk interface
+        /*String trunkInterfaceName = trunkInterface.getName();
+        IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
+        if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+            MonitorStartInput lldpMonitorInput = new MonitorStartInputBuilder().setConfig(new ConfigBuilder()
+                    .setSource(new SourceBuilder().setEndpointType(getInterfaceForMonitoring(trunkInterfaceName,
+                            ifTunnel.getTunnelSource())).build())
+                    .setMode(MonitoringMode.OneOne)
+                    .setProfileId(allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, MONITORING_INTERVAL, MONITORING_WINDOW,
+                            EtherTypes.Lldp)).build()).build();
+            try {
+                Future<RpcResult<MonitorStartOutput>> result = alivenessMonitorService.monitorStart(lldpMonitorInput);
+                RpcResult<MonitorStartOutput> rpcResult = result.get();
+                long monitorId;
+                if (rpcResult.isSuccessful()) {
+                    monitorId = rpcResult.getResult().getMonitorId();
+                    createOrUpdateInterfaceMonitorIdMap(dataBroker, trunkInterfaceName, monitorId);
+                    createOrUpdateMonitorIdInterfaceMap(dataBroker, trunkInterfaceName, monitorId);
+                    LOG.trace("Started LLDP monitoring with id {}", monitorId);
+                } else {
+                    LOG.warn("RPC Call to start monitoring returned with Errors {}", rpcResult.getErrors());
+                }
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.warn("Exception when starting monitoring", e);
+            }
+        }*/
+    }
+
+    public static void stopLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+                                          Interface trunkInterface) {
+        /*IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
+        if(!ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)){
+            return;
+        }
+        List<Long> monitorIds = getMonitorIdForInterface(dataBroker, trunkInterface.getName());
+        if (monitorIds == null) {
+            LOG.error("Monitor Id doesn't exist for Interface {}", trunkInterface);
+            return;
+        }
+        for (Long monitorId : monitorIds) {
+            String interfaceName = getInterfaceFromMonitorId(dataBroker, monitorId);
+            if (interfaceName != null) {
+                MonitorStopInput input = new MonitorStopInputBuilder().setMonitorId(monitorId).build();
+                alivenessMonitorService.monitorStop(input);
+                removeMonitorIdInterfaceMap(dataBroker, monitorId);
+                removeMonitorIdFromInterfaceMonitorIdMap(dataBroker, interfaceName, monitorId);
+                return;
+            }
+        }*/
+    }
+
+    public static String getInterfaceFromMonitorId(DataBroker broker, Long monitorId) {
+        InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+        Optional<MonitorIdInterface> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+        if(interfaceMonitorIdMap.isPresent()) {
+            return interfaceMonitorIdMap.get().getInterfaceName();
+        }
+        return null;
+    }
+
+    private static void removeMonitorIdInterfaceMap(DataBroker broker, long monitorId) {
+        InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+        Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+        if(monitorIdInterfaceMap.isPresent()) {
+            MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
+        }
+    }
+
+    private static void removeMonitorIdFromInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
+        InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+        Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+        if(interfaceMonitorIdMap.isPresent()) {
+            InterfaceMonitorId interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
+            List<Long> existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
+            if (existingMonitorIds != null && existingMonitorIds.contains(monitorId)) {
+                existingMonitorIds.remove(monitorId);
+                InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
+                interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
+                MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+            }
+        }
+    }
+
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface getInterfaceForMonitoring(String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress ipAddress) {
+        return new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.
+                endpoint.type.InterfaceBuilder().setInterfaceIp(ipAddress).setInterfaceName(interfaceName).build();
+    }
+
+    protected void handleTunnelMonitorEnabledUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+                                                     List<String> interfaceNames, boolean origMonitorEnabled, boolean updatedMonitorEnabled) {
+        for (String interfaceName : interfaceNames) {
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface tunnelInterface =
+                    InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
+            IfTunnel ifTunnel = tunnelInterface.getAugmentation(IfTunnel.class);
+            InterfaceManagerCommonUtils.updateTunnelMonitorDetailsInConfigDS(dataBroker, interfaceName, updatedMonitorEnabled, 3);
+            // Check if monitoring is started already
+            if (getMonitorIdForInterface(dataBroker, interfaceName) != null) {
+                // Get updated Interface details from Config DS
+                if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+                    if (updatedMonitorEnabled) {
+                        startLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
+                    } else {
+                        stopLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
+                    }
+                }
+            }
+        }
+    }
+
+    protected void handleTunnelMonitorIntervalUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+                                                      List<String> interfaceNames, long origMonitorInterval, long updatedMonitorInterval) {
+        for (String interfaceName : interfaceNames) {
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface tunnelInterface =
+                    InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
+            IfTunnel ifTunnel = tunnelInterface.getAugmentation(IfTunnel.class);
+            InterfaceManagerCommonUtils.updateTunnelMonitorDetailsInConfigDS(dataBroker, interfaceName, ifTunnel.isMonitorEnabled(), updatedMonitorInterval);
+            // Restart LLDP monitoring only if it's started already
+            List<Long> monitorIds = getMonitorIdForInterface(dataBroker, interfaceName);
+            if (monitorIds != null && monitorIds.size() > 1) {
+                // Get updated Interface details from Config DS
+                if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+                    stopLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
+                    startLLDPMonitoring(alivenessMonitorService, dataBroker,tunnelInterface);
+                }
+            }
+        }
+        // Delete old profile from Aliveness Manager
+        if (origMonitorInterval > 0) {
+            long profileId = allocateProfile(alivenessMonitorService, 4, origMonitorInterval, 4, EtherTypes.Lldp);
+            MonitorProfileDeleteInput  profileDeleteInput = new MonitorProfileDeleteInputBuilder().setProfileId(profileId).build();
+            alivenessMonitorService.monitorProfileDelete(profileDeleteInput);
+        }
+    }
+
+
+    public static void createOrUpdateInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
+        InterfaceMonitorId interfaceMonitorIdInstance;
+        List<Long> existingMonitorIds;
+        InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
+        InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+        Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+        if (interfaceMonitorIdMap.isPresent()) {
+            interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
+            existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
+            if (existingMonitorIds == null) {
+                existingMonitorIds = new ArrayList<>();
+            }
+            if (!existingMonitorIds.contains(monitorId)) {
+                existingMonitorIds.add(monitorId);
+                interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
+                MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+            }
+        } else {
+            existingMonitorIds = new ArrayList<>();
+            existingMonitorIds.add(monitorId);
+            interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setMonitorId(existingMonitorIds).setKey(new InterfaceMonitorIdKey(infName)).setInterfaceName(infName).build();
+            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+        }
+    }
+
+    public static void createOrUpdateMonitorIdInterfaceMap(DataBroker broker,String infName,  long monitorId) {
+        MonitorIdInterface monitorIdInterfaceInstance;
+        String existinginterfaceName;
+        MonitorIdInterfaceBuilder monitorIdInterfaceBuilder = new MonitorIdInterfaceBuilder();
+        InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+        Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+        if(monitorIdInterfaceMap.isPresent()) {
+            monitorIdInterfaceInstance = monitorIdInterfaceMap.get();
+            existinginterfaceName = monitorIdInterfaceInstance.getInterfaceName();
+            if(!existinginterfaceName.equals(infName)) {
+                monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
+                MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
+            }
+        } else {
+            monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setMonitorId(monitorId).setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
+            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
+        }
+    }
+
+    public static List<Long> getMonitorIdForInterface(DataBroker broker, String infName) {
+        InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+        Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+        if(interfaceMonitorIdMap.isPresent()) {
+            return interfaceMonitorIdMap.get().getMonitorId();
+        }
+        return null;
+    }
+
+    public static long allocateProfile(AlivenessMonitorService alivenessMonitor, long failureThreshold, long interval, long window, EtherTypes etherType ) {
+        MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().setProfile(new ProfileBuilder().setFailureThreshold(failureThreshold)
+                .setMonitorInterval(interval).setMonitorWindow(window).setProtocolType(etherType).build()).build();
+        try {
+            Future<RpcResult<MonitorProfileCreateOutput>> result = alivenessMonitor.monitorProfileCreate(input);
+            RpcResult<MonitorProfileCreateOutput> rpcResult = result.get();
+            if(rpcResult.isSuccessful()) {
+                return rpcResult.getResult().getProfileId();
+            } else {
+                LOG.warn("RPC Call to Get Profile Id Id returned with Errors {}", rpcResult.getErrors());
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Exception when allocating profile Id",e);
+        }
+        return 0;
+    }
+}
\ No newline at end of file
index c3fafa07790a41890fa879ad4ffde6a524744432..0d134849438229e3bbe07d1bf28195b03b8d51af 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -29,8 +30,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeMplsOverGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
@@ -110,4 +110,24 @@ public class InterfaceManagerCommonUtils {
     public static String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
         return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
     }
+
+    public static void setOpStateForInterface(DataBroker broker, String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opStatus) {
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceId = IfmUtil.buildStateInterfaceId(interfaceName);
+        InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceData = ifaceBuilder.setOperStatus(opStatus).build();
+        MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceData);
+    }
+
+    public static void updateTunnelMonitorDetailsInConfigDS(DataBroker broker, String interfaceName, boolean monitorEnabled, long monitorInterval) {
+        InstanceIdentifier<Interface> id = IfmUtil.buildId(interfaceName);
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder();
+        ifaceBuilder.setKey(new InterfaceKey(interfaceName));
+        IfTunnelBuilder ifTunnelBuilder = new IfTunnelBuilder();
+        ifTunnelBuilder.setMonitorEnabled(monitorEnabled);
+        ifTunnelBuilder.setMonitorInterval(monitorInterval);
+        ifaceBuilder.addAugmentation(IfTunnel.class, ifTunnelBuilder.build());
+
+        LOG.trace("Updating trunk interface {} in Config DS", interfaceName);
+        MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, ifaceBuilder.build());
+    }
 }
\ No newline at end of file
index a123fccc1e846bcfaa41de4bfe24705231e291cb..3ce243cde34db7a59ef4ef89ba134d25c9db7286 100644 (file)
@@ -8,12 +8,17 @@
 package org.opendaylight.vpnservice.interfacemgr.commons;
 
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.eclipse.xtend.lib.annotations.Data;
 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;
 import org.opendaylight.idmanager.IdManager;
 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.BridgeInterfaceInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.BridgeRefInfo;
@@ -32,10 +37,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.met
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
 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 java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
 public class InterfaceMetaUtils {
     public static InstanceIdentifier<BridgeRefEntry> getBridgeRefEntryIdentifier(BridgeRefEntryKey bridgeRefEntryKey) {
         InstanceIdentifier.InstanceIdentifierBuilder<BridgeRefEntry> bridgeRefEntryInstanceIdentifierBuilder =
@@ -168,4 +178,15 @@ public class InterfaceMetaUtils {
         }
         IfmUtil.releaseId(idManager, IfmConstants.IFM_IDPOOL_NAME, infName);
     }
+
+    public static void createBridgeRefEntry(BigInteger dpnId, InstanceIdentifier<?> bridgeIid,
+                                            WriteTransaction tx){
+        BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpnId);
+        InstanceIdentifier<BridgeRefEntry> bridgeEntryId =
+                InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
+        BridgeRefEntryBuilder tunnelDpnBridgeEntryBuilder =
+                new BridgeRefEntryBuilder().setKey(bridgeRefEntryKey).setDpid(dpnId)
+                        .setBridgeReference(new OvsdbBridgeRef(bridgeIid));
+        tx.put(LogicalDatastoreType.OPERATIONAL, bridgeEntryId, tunnelDpnBridgeEntryBuilder.build(), true);
+    }
 }
\ No newline at end of file
diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/listeners/AlivenessMonitorListener.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/listeners/AlivenessMonitorListener.java
new file mode 100644 (file)
index 0000000..9f8b84c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 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.vpnservice.interfacemgr.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+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.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.LivenessState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * This class listens for interface creation/removal/update in Configuration DS.
+ * This is used to handle interfaces for base of-ports.
+ */
+public class AlivenessMonitorListener implements org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorListener {
+    private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorListener.class);
+    private DataBroker dataBroker;
+
+    public AlivenessMonitorListener(final DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+    }
+
+    @Override
+    public void onMonitorEvent(MonitorEvent notification) {
+        Long monitorId = notification.getEventData().getMonitorId();
+        String trunkInterfaceName = AlivenessMonitorUtils.getInterfaceFromMonitorId(dataBroker, monitorId);
+        if (trunkInterfaceName == null) {
+            LOG.debug("Either monitoring for interface - {} not started by Interfacemgr or it is not LLDP monitoring", trunkInterfaceName);
+            return;
+        }
+        LivenessState livenessState = notification.getEventData().getMonitorState();
+        Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(trunkInterfaceName),
+                dataBroker);
+        IfTunnel tunnelInfo = interfaceInfo.getAugmentation(IfTunnel.class);
+        // Not handling monitoring event if it is GRE Trunk Interface.
+        if (tunnelInfo.getTunnelInterfaceType().isAssignableFrom(TunnelTypeGre.class)) {
+            return;
+        }
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState =
+                livenessState == LivenessState.Up ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up :
+                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+        InterfaceManagerCommonUtils.setOpStateForInterface(dataBroker, trunkInterfaceName, opState);
+    }
+
+}
\ No newline at end of file
index 6e911667b56576ba0c7027419cfd9bcd4d2e0898..be8bd8d15b0072c6145506126ba1cd19d108aa27 100644 (file)
@@ -16,8 +16,10 @@ import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 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.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -35,11 +37,17 @@ public class InterfaceConfigListener extends AsyncDataTreeChangeListenerBase<Int
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceConfigListener.class);
     private DataBroker dataBroker;
     private IdManagerService idManager;
+    private AlivenessMonitorService alivenessMonitorService;
+    private IMdsalApiManager mdsalApiManager;
 
-    public InterfaceConfigListener(final DataBroker dataBroker, final IdManagerService idManager) {
+    public InterfaceConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
+                                   final AlivenessMonitorService alivenessMonitorService,
+                                   final IMdsalApiManager mdsalApiManager) {
         super(Interface.class, InterfaceConfigListener.class);
         this.dataBroker = dataBroker;
         this.idManager = idManager;
+        this.alivenessMonitorService = alivenessMonitorService;
+        this.mdsalApiManager = mdsalApiManager;
     }
 
     @Override
@@ -132,7 +140,8 @@ public class InterfaceConfigListener extends AsyncDataTreeChangeListenerBase<Int
         public List<ListenableFuture<Void>> call() throws Exception {
             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
             // to call the respective helpers.
-            return OvsInterfaceConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew, idManager);
+            return OvsInterfaceConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew,
+                    idManager, alivenessMonitorService, mdsalApiManager);
         }
 
         @Override
@@ -166,7 +175,8 @@ public class InterfaceConfigListener extends AsyncDataTreeChangeListenerBase<Int
         public List<ListenableFuture<Void>> call() throws Exception {
             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
             // to call the respective helpers.
-            return OvsInterfaceConfigUpdateHelper.updateConfiguration(dataBroker, idManager, interfaceNew, interfaceOld);
+            return OvsInterfaceConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager,
+                    mdsalApiManager, interfaceNew, interfaceOld);
         }
 
         @Override
@@ -201,7 +211,8 @@ public class InterfaceConfigListener extends AsyncDataTreeChangeListenerBase<Int
         public List<ListenableFuture<Void>> call() throws Exception {
             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
             // to call the respective helpers.
-            return OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, interfaceOld, idManager, parentRefs);
+            return OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, alivenessMonitorService,
+                    interfaceOld, idManager, mdsalApiManager, parentRefs);
         }
 
         @Override
index e99e2912029973c97fb7cc80e15c9638efa98414..d2e56baf4480f2d9eba7487bff33448cc7f6f2de 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeCon
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -44,12 +45,15 @@ public class InterfaceInventoryStateListener extends AsyncDataChangeListenerBase
     private DataBroker dataBroker;
     private IdManagerService idManager;
     private IMdsalApiManager mdsalApiManager;
+    private AlivenessMonitorService alivenessMonitorService;
 
-    public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManager, final IMdsalApiManager mdsalApiManager) {
+    public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManager,
+                                           final IMdsalApiManager mdsalApiManager, final AlivenessMonitorService alivenessMonitorService) {
         super(FlowCapableNodeConnector.class, InterfaceInventoryStateListener.class);
         this.dataBroker = dataBroker;
         this.idManager = idManager;
         this.mdsalApiManager = mdsalApiManager;
+        this.alivenessMonitorService = alivenessMonitorService;
     }
 
     @Override
@@ -73,11 +77,10 @@ public class InterfaceInventoryStateListener extends AsyncDataChangeListenerBase
                           FlowCapableNodeConnector flowCapableNodeConnectorOld) {
         LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
         String portName = flowCapableNodeConnectorOld.getName();
-        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
 
-        InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager, key,
-                flowCapableNodeConnectorOld, portName);
+        InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
+                key, flowCapableNodeConnectorOld, portName);
         coordinator.enqueueJob(portName, interfaceStateRemoveWorker);
     }
 
@@ -124,7 +127,7 @@ public class InterfaceInventoryStateListener extends AsyncDataChangeListenerBase
         public Object call() throws Exception {
             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
             // to call the respective helpers.
-             return OvsInterfaceStateAddHelper.addState(dataBroker, idManager, mdsalApiManager, nodeConnectorId,
+             return OvsInterfaceStateAddHelper.addState(dataBroker, idManager, mdsalApiManager, alivenessMonitorService, nodeConnectorId,
                      portName, fcNodeConnectorNew);
         }
 
@@ -159,7 +162,7 @@ public class InterfaceInventoryStateListener extends AsyncDataChangeListenerBase
         public Object call() throws Exception {
             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
             // to call the respective helpers.
-            return OvsInterfaceStateUpdateHelper.updateState(key, dataBroker, portName,
+            return OvsInterfaceStateUpdateHelper.updateState(key, alivenessMonitorService, dataBroker, portName,
                     fcNodeConnectorNew, fcNodeConnectorOld);
         }
 
@@ -194,7 +197,8 @@ public class InterfaceInventoryStateListener extends AsyncDataChangeListenerBase
         public Object call() throws Exception {
             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
             // to call the respective helpers.
-            return OvsInterfaceStateRemoveHelper.removeState(idManager, mdsalApiManager, key, dataBroker, portName, fcNodeConnectorOld);
+            return OvsInterfaceStateRemoveHelper.removeState(idManager, mdsalApiManager, alivenessMonitorService,
+                    key, dataBroker, portName, fcNodeConnectorOld);
         }
 
         @Override
index eb43d689abe927007580d8263a530d92686d44dc..1c17f9d9d253218b135c6b1a6f97e1daa5bda3b7 100644 (file)
@@ -15,8 +15,10 @@ import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigAddHelper;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigRemoveHelper;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 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.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
@@ -31,11 +33,17 @@ public class VlanMemberConfigListener extends AsyncDataTreeChangeListenerBase<In
     private static final Logger LOG = LoggerFactory.getLogger(VlanMemberConfigListener.class);
     private DataBroker dataBroker;
     private IdManagerService idManager;
+    private AlivenessMonitorService alivenessMonitorService;
+    private IMdsalApiManager mdsalApiManager;
 
-    public VlanMemberConfigListener(final DataBroker dataBroker, final IdManagerService idManager) {
+    public VlanMemberConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
+                                    final AlivenessMonitorService alivenessMonitorService,
+                                    final IMdsalApiManager mdsalApiManager) {
         super(Interface.class, VlanMemberConfigListener.class);
         this.dataBroker = dataBroker;
         this.idManager = idManager;
+        this.alivenessMonitorService = alivenessMonitorService;
+        this.mdsalApiManager = mdsalApiManager;
     }
 
     @Override
@@ -179,8 +187,8 @@ public class VlanMemberConfigListener extends AsyncDataTreeChangeListenerBase<In
         public List<ListenableFuture<Void>> call() throws Exception {
             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
             // to call the respective helpers.
-            return OvsVlanMemberConfigUpdateHelper.updateConfiguration(dataBroker, parentRefsNew, interfaceOld,
-                    ifL2vlanNew, interfaceNew, idManager);
+            return OvsVlanMemberConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService,
+                    parentRefsNew, interfaceOld, ifL2vlanNew, interfaceNew, idManager, mdsalApiManager);
         }
     }
 
index 70fca216c73d681aaf45ccbf55ffbca43826cd06..07a4709d91eaaced4740a02c99865b613537fd56 100644 (file)
@@ -9,15 +9,21 @@ package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
+import org.eclipse.xtend.lib.annotations.Data;
 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;
 import org.opendaylight.idmanager.IdManager;
 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
 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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
@@ -26,6 +32,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.ConfigBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
@@ -36,29 +45,33 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.met
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
 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.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 public class OvsInterfaceConfigAddHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigAddHelper.class);
 
     public static List<ListenableFuture<Void>> addConfiguration(DataBroker dataBroker, ParentRefs parentRefs,
-                                                                Interface interfaceNew, IdManagerService idManager) {
+                                                                Interface interfaceNew, IdManagerService idManager,
+                                                                AlivenessMonitorService alivenessMonitorService,
+                                                                IMdsalApiManager mdsalApiManager) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
 
         IfTunnel ifTunnel = interfaceNew.getAugmentation(IfTunnel.class);
         if (ifTunnel != null) {
-            addTunnelConfiguration(dataBroker, parentRefs, interfaceNew, idManager, futures);
+            addTunnelConfiguration(dataBroker, parentRefs, interfaceNew, idManager, alivenessMonitorService,
+                    mdsalApiManager, futures);
             return futures;
         }
 
@@ -124,6 +137,8 @@ public class OvsInterfaceConfigAddHelper {
 
     private static void addTunnelConfiguration(DataBroker dataBroker, ParentRefs parentRefs,
                                               Interface interfaceNew, IdManagerService idManager,
+                                              AlivenessMonitorService alivenessMonitorService,
+                                              IMdsalApiManager mdsalApiManager,
                                               List<ListenableFuture<Void>> futures) {
         LOG.debug("adding tunnel configuration for {}", interfaceNew.getName());
         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
@@ -140,8 +155,6 @@ public class OvsInterfaceConfigAddHelper {
             return;
         }
 
-        //createBridgeEntryIfNotPresent(dpId, dataBroker, t);
-
         BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpId);
         BridgeInterfaceEntryKey bridgeInterfaceEntryKey = new BridgeInterfaceEntryKey(interfaceNew.getName());
 
@@ -167,6 +180,16 @@ public class OvsInterfaceConfigAddHelper {
                 String bridgeName = ovsdbBridgeAugmentation.getBridgeName().getValue();
                 SouthboundUtils.addPortToBridge(bridgeIid, interfaceNew,
                         ovsdbBridgeAugmentation, bridgeName, interfaceNew.getName(), dataBroker, futures);
+
+                // if TEP is already configured on switch, start LLDP monitoring and program tunnel ingress flow
+                NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(interfaceNew, dataBroker);
+                if(ncId != null){
+                    long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(ncId));
+                    InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, interfaceNew.getAugmentation(IfTunnel.class),
+                            dpId, portNo, interfaceNew, NwConstants.ADD_FLOW);
+                    // start LLDP monitoring for the tunnel interface
+                    AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew);
+                }
             }
         }
     }
index 03f9c0600c40783e0b728da5a6b1c9d4df1b03f5..8a4748c66e0d6abb561361639242862580be4424 100644 (file)
@@ -13,9 +13,12 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.idmanager.IdManager;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
@@ -23,6 +26,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
@@ -49,18 +55,22 @@ import java.util.List;
 public class OvsInterfaceConfigRemoveHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigRemoveHelper.class);
 
-    public static List<ListenableFuture<Void>> removeConfiguration(DataBroker dataBroker, Interface interfaceOld,
-                                                                   IdManagerService idManager, ParentRefs parentRefs) {
+    public static List<ListenableFuture<Void>> removeConfiguration(DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService,
+                                                                   Interface interfaceOld,
+                                                                   IdManagerService idManager,
+                                                                   IMdsalApiManager mdsalApiManager,
+                                                                   ParentRefs parentRefs) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
 
         IfTunnel ifTunnel = interfaceOld.getAugmentation(IfTunnel.class);
         if (ifTunnel != null) {
-            removeTunnelConfiguration(parentRefs, dataBroker, interfaceOld, idManager, t);
+            removeTunnelConfiguration(alivenessMonitorService, parentRefs, dataBroker, interfaceOld,
+                    idManager, mdsalApiManager, futures);
         }else {
             removeVlanConfiguration(dataBroker, interfaceOld, t);
+            futures.add(t.submit());
         }
-        futures.add(t.submit());
         return futures;
     }
 
@@ -123,9 +133,12 @@ public class OvsInterfaceConfigRemoveHelper {
         }
     }
 
-    private static void removeTunnelConfiguration(ParentRefs parentRefs, DataBroker dataBroker, Interface interfaceOld,
-                                                  IdManagerService idManager, WriteTransaction t) {
+    private static void removeTunnelConfiguration(AlivenessMonitorService alivenessMonitorService, ParentRefs parentRefs,
+                                                  DataBroker dataBroker, Interface interfaceOld,
+                                                  IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+                                                  List<ListenableFuture<Void>> futures) {
 
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
         BigInteger dpId = null;
         if (parentRefs != null) {
             dpId = parentRefs.getDatapathNodeIdentifier();
@@ -146,6 +159,14 @@ public class OvsInterfaceConfigRemoveHelper {
             InstanceIdentifier<TerminationPoint> tpIid = SouthboundUtils.createTerminationPointInstanceIdentifier(
                     InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceOld.getName());
             t.delete(LogicalDatastoreType.CONFIGURATION, tpIid);
+
+            // delete tunnel ingress flow
+            NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(interfaceOld, dataBroker);
+            long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(ncId));
+            InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager,
+                    interfaceOld.getAugmentation(IfTunnel.class),
+                    dpId, portNo, interfaceOld,
+                    NwConstants.DEL_FLOW);
         }
 
         BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpId);
@@ -170,5 +191,8 @@ public class OvsInterfaceConfigRemoveHelper {
                             bridgeInterfaceEntryKey);
             t.delete(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryIid);
         }
+        futures.add(t.submit());
+        // stop LLDP monitoring for the tunnel interface
+        AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceOld);
     }
 }
\ No newline at end of file
index 0770bd5b1648f49fb88b9a3ac3aeb5b720dcbfe0..328c37c10e7457b33794515028a4c6518121ea54 100644 (file)
@@ -13,8 +13,11 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.idmanager.IdManager;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
@@ -22,6 +25,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.LivenessState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
@@ -29,6 +36,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.met
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,18 +44,19 @@ import org.slf4j.LoggerFactory;
 import java.util.ArrayList;
 import java.util.List;
 
-public class OvsInterfaceConfigUpdateHelper {
+public class OvsInterfaceConfigUpdateHelper{
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigUpdateHelper.class);
 
-    public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker,  IdManagerService idManager,
+    public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker,  AlivenessMonitorService alivenessMonitorService,
+                                                                   IdManagerService idManager, IMdsalApiManager mdsalApiManager,
                                                                    Interface interfaceNew, Interface interfaceOld) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
 
         if(portAttributesModified(interfaceOld, interfaceNew)) {
-            futures.addAll(OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, interfaceOld, idManager,
-                    interfaceOld.getAugmentation(ParentRefs.class)));
+            futures.addAll(OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, alivenessMonitorService, interfaceOld, idManager,
+                    mdsalApiManager, interfaceOld.getAugmentation(ParentRefs.class)));
             futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
-                    interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager));
+                    interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager,alivenessMonitorService,mdsalApiManager));
             return futures;
         }
 
@@ -55,7 +64,7 @@ public class OvsInterfaceConfigUpdateHelper {
                 InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceNew.getName(), dataBroker);
         if (ifState == null) {
             futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
-                    interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager));
+                    interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager, alivenessMonitorService, mdsalApiManager));
             return futures;
         }
 
@@ -86,6 +95,10 @@ public class OvsInterfaceConfigUpdateHelper {
             IfL2vlan ifL2vlan = interfaceNew.getAugmentation(IfL2vlan.class);
             if (ifL2vlan == null || ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
                 futures.add(t.submit());
+                // stop tunnel monitoring if admin state is disabled for a vxlan trunk interface
+                if(!interfaceNew.isEnabled()){
+                    AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew);
+                }
                 return futures;
             }
 
@@ -159,4 +172,5 @@ public class OvsInterfaceConfigUpdateHelper {
 
         return false;
     }
+
 }
\ No newline at end of file
index 703322653f8ce402513d3579819d7b23bc40cd90..9d5a578aa4c53f5f2aa0b51d7c5149a05c9e92ee 100644 (file)
@@ -15,9 +15,11 @@ import org.opendaylight.idmanager.IdManager;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 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.state.Interface.OperStatus;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
@@ -33,9 +35,10 @@ import java.util.List;
 
 public class OvsVlanMemberConfigUpdateHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsVlanMemberConfigUpdateHelper.class);
-    public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, ParentRefs parentRefsNew,
+    public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService, ParentRefs parentRefsNew,
                                                                    Interface interfaceOld, IfL2vlan ifL2vlanNew,
-                                                                   Interface interfaceNew, IdManagerService idManager) {
+                                                                   Interface interfaceNew, IdManagerService idManager,
+                                                                   IMdsalApiManager mdsalApiManager) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
         ParentRefs parentRefsOld = interfaceOld.getAugmentation(ParentRefs.class);
 
@@ -48,7 +51,7 @@ public class OvsVlanMemberConfigUpdateHelper {
 
         if (interfaceChildEntry == null) {
             futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
-                    interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager));
+                    interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager, alivenessMonitorService, mdsalApiManager));
             return futures;
         }
 
index 8a3faba162bb00794f34101978649b2078fcac50..e23fb3f64a543d60dfe1f5b7bcb54268cd072410 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.idmanager.IdManager;
 import org.opendaylight.vpnservice.VpnConstants;
 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
 import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
@@ -28,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.Fl
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
@@ -54,7 +56,8 @@ import java.util.List;
 public class OvsInterfaceStateAddHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateAddHelper.class);
 
-    public static List<ListenableFuture<Void>> addState(DataBroker dataBroker, IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+    public static List<ListenableFuture<Void>> addState(DataBroker dataBroker, IdManagerService idManager,
+                                                        IMdsalApiManager mdsalApiManager,AlivenessMonitorService alivenessMonitorService,
                                                         NodeConnectorId nodeConnectorId, String portName, FlowCapableNodeConnector fcNodeConnectorNew) {
         LOG.debug("Adding Interface State to Oper DS for port: {}", portName);
         List<ListenableFuture<Void>> futures = new ArrayList<>();
@@ -103,6 +106,7 @@ public class OvsInterfaceStateAddHelper {
             InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel,dpId, portNo, iface,
                     NwConstants.ADD_FLOW);
             futures.add(transaction.submit());
+            AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
             return futures;
         }
 
index 2aa85d2675e39037ea11347926485c4564510f6f..88af8f816baab55a01b1493aba82fb53dda93906 100644 (file)
@@ -12,6 +12,7 @@ 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;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
@@ -24,6 +25,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeCon
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
@@ -41,6 +43,7 @@ public class OvsInterfaceStateRemoveHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateRemoveHelper.class);
 
     public static List<ListenableFuture<Void>> removeState(IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+                                                           AlivenessMonitorService alivenessMonitorService,
                                                            InstanceIdentifier<FlowCapableNodeConnector> key,
                                                            DataBroker dataBroker, String portName, FlowCapableNodeConnector fcNodeConnectorOld) {
         LOG.debug("Removing interface-state for port: {}", portName);
@@ -66,7 +69,7 @@ public class OvsInterfaceStateRemoveHelper {
             return futures;
         }
 
-        // If this interface is a tunnel interface, remove the tunnel ingress flow
+        // If this interface is a tunnel interface, remove the tunnel ingress flow and stop lldp monitoring
         IfTunnel tunnel = iface.getAugmentation(IfTunnel.class);
         if(tunnel != null){
             NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
@@ -74,6 +77,8 @@ public class OvsInterfaceStateRemoveHelper {
             long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
             InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel, dpId, portNo, iface,
                     NwConstants.DEL_FLOW);
+            futures.add(transaction.submit());
+            AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
             return futures;
         }
 
index 02a3a2ace4b75378a70845e77260d25515e67e9a..9b99aee56065aaa9aa7ad88c69bcb4cb59b0a172 100644 (file)
@@ -12,6 +12,7 @@ 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;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
@@ -20,6 +21,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
@@ -34,6 +36,7 @@ public class OvsInterfaceStateUpdateHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateUpdateHelper.class);
 
     public static List<ListenableFuture<Void>> updateState(InstanceIdentifier<FlowCapableNodeConnector> key,
+                                                           AlivenessMonitorService alivenessMonitorService,
                                                            DataBroker dataBroker, String portName,
                                                            FlowCapableNodeConnector flowCapableNodeConnectorNew,
                                                            FlowCapableNodeConnector flowCapableNodeConnectorOld) {
@@ -73,13 +76,12 @@ public class OvsInterfaceStateUpdateHelper {
 
         InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(portName);
         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
-
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface = null;
         boolean modified = false;
         if (opstateModified) {
             LOG.debug("Opstate Modified for Port: {}", portName);
             InterfaceKey interfaceKey = new InterfaceKey(portName);
-            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
-                    InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+             iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
 
             // If interface config admin state is disabled, set operstate of the Interface State entity to Down.
             if (iface != null && !iface.isEnabled()) {
@@ -116,6 +118,11 @@ public class OvsInterfaceStateUpdateHelper {
                     InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
             if (interfaceParentEntry == null) {
                 futures.add(t.submit());
+                // start/stop monitoring based on opState
+                if(operStatusNew == Interface.OperStatus.Down )
+                    AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
+                else
+                    AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService,dataBroker, iface);
                 return futures;
             }
 
index 4fa4c1bf0b4c951c2af6fcecb2594158c372535c..ae9dccf33575c3886974a88a126d30514564157c 100644 (file)
@@ -41,7 +41,7 @@ public class OvsInterfaceTopologyStateAddHelper {
     public static List<ListenableFuture<Void>> addPortToBridge(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
                                                                OvsdbBridgeAugmentation bridgeNew, DataBroker dataBroker) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
 
         if (bridgeNew.getDatapathId() == null) {
             LOG.warn("DataPathId found as null for Bridge Augmentation: {}... retrying...", bridgeNew);
@@ -62,13 +62,11 @@ public class OvsInterfaceTopologyStateAddHelper {
             return futures;
         }
 
-        BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpnId);
-        InstanceIdentifier<BridgeRefEntry> bridgeEntryId =
-                InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
-        BridgeRefEntryBuilder tunnelDpnBridgeEntryBuilder =
-                new BridgeRefEntryBuilder().setKey(bridgeRefEntryKey).setDpid(dpnId)
-                        .setBridgeReference(new OvsdbBridgeRef(bridgeIid));
-        t.put(LogicalDatastoreType.OPERATIONAL, bridgeEntryId, tunnelDpnBridgeEntryBuilder.build(), true);
+        // create bridge reference entry in interface meta operational DS
+        InterfaceMetaUtils.createBridgeRefEntry(dpnId, bridgeIid, writeTransaction);
+
+        // FIX for OVSDB Bug - manually copying the bridge info from topology operational DS to config DS
+        SouthboundUtils.addBridge(bridgeIid, bridgeNew, dataBroker, futures);
 
         BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpnId);
         InstanceIdentifier<BridgeEntry> bridgeEntryInstanceIdentifier =
@@ -77,7 +75,7 @@ public class OvsInterfaceTopologyStateAddHelper {
                 InterfaceMetaUtils.getBridgeEntryFromConfigDS(bridgeEntryInstanceIdentifier,
                         dataBroker);
         if (bridgeEntry == null) {
-            futures.add(t.submit());
+            futures.add(writeTransaction.submit());
             return futures;
         }
 
@@ -88,12 +86,10 @@ public class OvsInterfaceTopologyStateAddHelper {
             Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
             if (iface.getAugmentation(IfTunnel.class) != null) {
                 SouthboundUtils.addPortToBridge(bridgeIid, iface, bridgeNew, bridgeName, portName, dataBroker, futures);
-                InterfaceMetaUtils.createBridgeInterfaceEntryInConfigDS(bridgeEntryKey,
-                        new BridgeInterfaceEntryKey(portName), portName, t);
             }
         }
 
-        futures.add(t.submit());
+        futures.add(writeTransaction.submit());
         return futures;
     }
 }
\ No newline at end of file
index 90fcf3607777ff943e13d563e7b7cf7af222b37f..dd4f25db0712bd1c118d37175d63a1bd7f21e866 100644 (file)
@@ -13,6 +13,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
@@ -42,6 +43,9 @@ public class OvsInterfaceTopologyStateRemoveHelper {
                 InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
         t.delete(LogicalDatastoreType.OPERATIONAL, bridgeEntryId);
 
+        // FIX for ovsdb bug for delete TEP
+        SouthboundUtils.deleteBridge(bridgeIid, dataBroker, futures);
+
         futures.add(t.submit());
         return futures;
     }
index 690a5eee73508dfe808fac812ae94caec4e3eff1..4bf4d42f30ca91a8003280e7e032c8a931ad773b 100644 (file)
@@ -20,11 +20,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
 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;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
 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.NodeBuilder;
 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.network.topology.topology.node.TerminationPointBuilder;
@@ -57,6 +59,26 @@ public class SouthboundUtils {
         futures.add(tx.submit());
     }
 
+    public static void addBridge(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+                                 OvsdbBridgeAugmentation bridgeAugmentation,
+                                 DataBroker dataBroker, List<ListenableFuture<Void>> futures){
+        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+        NodeId nodeId = InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)).getNodeId();
+        NodeBuilder bridgeNodeBuilder = new NodeBuilder();
+        bridgeNodeBuilder.setNodeId(nodeId);
+        bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, bridgeAugmentation);
+        tx.put(LogicalDatastoreType.CONFIGURATION, createNodeInstanceIdentifier(nodeId), bridgeNodeBuilder.build(), true);
+        futures.add(tx.submit());
+    }
+
+    public static void deleteBridge(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+                                 DataBroker dataBroker, List<ListenableFuture<Void>> futures){
+        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+        NodeId nodeId = InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)).getNodeId();
+        tx.delete(LogicalDatastoreType.CONFIGURATION, createNodeInstanceIdentifier(nodeId));
+        futures.add(tx.submit());
+    }
+
     private static void addVlanPortToBridge(InstanceIdentifier<?> bridgeIid, IfL2vlan ifL2vlan,
                                               OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName,
                                               String portName, DataBroker dataBroker, WriteTransaction t) {
@@ -160,4 +182,11 @@ public class SouthboundUtils {
         LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
         return terminationPointPath;
     }
+
+    public static InstanceIdentifier<Node> createNodeInstanceIdentifier(NodeId nodeId) {
+        return InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
+                .child(Node.class,new NodeKey(nodeId));
+    }
 }
\ No newline at end of file
index 14ab2e60ccd4fa79b4a7602c8508875dfaea6c79..2eae05ca3ef17e02fdabdd1d6427ef31c05003f8 100644 (file)
@@ -28,6 +28,7 @@ public class InterfacemgrImplModule extends org.opendaylight.yang.gen.v1.urn.ope
     public java.lang.AutoCloseable createInstance() {
         InterfacemgrProvider provider = new InterfacemgrProvider();
         provider.setRpcProviderRegistry(getRpcRegistryDependency());
+        provider.setNotificationService(getNotificationServiceDependency());
         provider.setMdsalManager(getMdsalutilDependency());
         getBrokerDependency().registerProvider(provider);
         return provider;
index 471880160cc72aa4cd3879537e89706857909c87..18227c5913c077885459eb6985ec3d3c5ab1e37b 100644 (file)
@@ -4,6 +4,7 @@ module interfacemgr-impl {
     prefix "interfacemgr-impl";
 
     import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-sal-binding-broker-impl { prefix md-sal-binding-impl; revision-date 2013-10-28;}
     import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
     import odl-interface {prefix odlif; revision-date 2015-03-31;}
     import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
@@ -49,6 +50,14 @@ module interfacemgr-impl {
                     }
                 }
             }
+            container notification-service {
+                 uses config:service-ref {
+                     refine type {
+                         mandatory true;
+                         config:required-identity md-sal-binding-impl:binding-new-notification-service;
+                     }
+                 }
+            }
         }
     }
 }
index 489031c4de4bdb0f515370b894a8766c72f9f6f6..4b626cf648f45fe356e7f2bc6494588839514947 100644 (file)
@@ -39,6 +39,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.Fl
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.IfIndexesInterfaceMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterface;
@@ -85,6 +86,7 @@ public class StateInterfaceTest {
     @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
     @Mock ReadOnlyTransaction mockReadTx;
     @Mock WriteTransaction mockWriteTx;
+    @Mock AlivenessMonitorService alivenessMonitorService;
 
     OvsInterfaceStateAddHelper addHelper;
     OvsInterfaceStateRemoveHelper removeHelper;
@@ -147,7 +149,8 @@ public class StateInterfaceTest {
                 .setIdKey(InterfaceManagerTestUtil.interfaceName).build();
         doReturn(idOutputOptional).when(idManager).allocateId(getIdInput);
 
-        addHelper.addState(dataBroker, idManager, mdsalManager, nodeConnectorId, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
+        addHelper.addState(dataBroker, idManager, mdsalManager, alivenessMonitorService,
+                nodeConnectorId, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
 
         //Add some verifications
         verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier,
@@ -171,7 +174,7 @@ public class StateInterfaceTest {
 
         doReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build())).when(idManager).releaseId(getIdInput);
 
-        removeHelper.removeState(idManager, mdsalManager, fcNodeConnectorId, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
+        removeHelper.removeState(idManager, mdsalManager, alivenessMonitorService, fcNodeConnectorId, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
 
         verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
         verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, ifIndexId);
@@ -205,7 +208,7 @@ public class StateInterfaceTest {
         fcNodeConnectorOldupdate.setState(b2.build());
         fcNodeConnectorNewupdate.setState(b3.build());
 
-        updateHelper.updateState(fcNodeConnectorId, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNewupdate.build(), fcNodeConnectorOldupdate.build());
+        updateHelper.updateState(fcNodeConnectorId, alivenessMonitorService, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNewupdate.build(), fcNodeConnectorOldupdate.build());
 
         verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL,interfaceStateIdentifier,stateInterface);
     }
index fc57cdd73e4cd1c6378da3069a8d63699c826418..172d1935810543acbf5688deaefc1ad1cf0bbdd3 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 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.state.Interface.OperStatus;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
@@ -34,6 +35,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
@@ -85,10 +87,12 @@ public class TunnelInterfaceConfigurationTest {
 
     @Mock DataBroker dataBroker;
     @Mock IdManagerService idManager;
+    @Mock AlivenessMonitorService alivenessMonitorService;
     @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
     @Mock ReadOnlyTransaction mockReadTx;
     @Mock WriteTransaction mockWriteTx;
-
+    @Mock
+    IMdsalApiManager mdsalApiManager;
     OvsInterfaceConfigAddHelper addHelper;
     OvsInterfaceConfigRemoveHelper removeHelper;
     OvsInterfaceConfigUpdateHelper updateHelper;
@@ -158,7 +162,8 @@ public class TunnelInterfaceConfigurationTest {
         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
                 LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
 
-        addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager);
+        addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager,
+                alivenessMonitorService, mdsalApiManager);
 
         //Add some verifications
         verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryInstanceIdentifier, bridgeInterfaceEntry, true);
@@ -168,13 +173,15 @@ public class TunnelInterfaceConfigurationTest {
     public void testAddGreInterfaceWhenSwitchIsConnected() {
         Optional<BridgeRefEntry> expectedBridgeRefEntry = Optional.of(bridgeRefEntry);
         Optional<OvsdbBridgeAugmentation> expectedOvsdbBridgeAugmentation = Optional.of(ovsdbBridgeAugmentation);
-
+        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+                LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
         doReturn(Futures.immediateCheckedFuture(expectedBridgeRefEntry)).when(mockReadTx).read(
                 LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
         doReturn(Futures.immediateCheckedFuture(expectedOvsdbBridgeAugmentation)).when(mockReadTx).read(
                 LogicalDatastoreType.OPERATIONAL, ovsdbBridgeAugmentationInstanceIdentifier);
 
-        addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager);
+        addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager,
+                alivenessMonitorService, mdsalApiManager);
 
         //Add some verifications
         verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryInstanceIdentifier ,
@@ -188,17 +195,21 @@ public class TunnelInterfaceConfigurationTest {
     public void testDeleteGreInterfaceWhenSwitchIsConnected() {
         Optional<BridgeRefEntry> expectedBridgeRefEntry = Optional.of(bridgeRefEntry);
         Optional<BridgeEntry> expectedBridgeEntry = Optional.of(bridgeEntry);
+        Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedInterfaceState = Optional.of(stateInterface);
         doReturn(Futures.immediateCheckedFuture(expectedBridgeRefEntry)).when(mockReadTx).read(
                 LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
         doReturn(Futures.immediateCheckedFuture(expectedBridgeEntry)).when(mockReadTx).read(
                 LogicalDatastoreType.CONFIGURATION, bridgeEntryIid);
+        doReturn(Futures.immediateCheckedFuture(expectedInterfaceState)).when(mockReadTx).read(
+                LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
 
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
         ifaceBuilder.setOperStatus(OperStatus.Down);
         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(tunnelInterfaceEnabled.getName()));
         stateInterface = ifaceBuilder.build();
 
-        removeHelper.removeConfiguration(dataBroker, tunnelInterfaceEnabled, idManager, parentRefs);
+        removeHelper.removeConfiguration(dataBroker, alivenessMonitorService, tunnelInterfaceEnabled, idManager,
+                mdsalApiManager, parentRefs);
 
         //Add some verifications
         verify(mockWriteTx).delete(LogicalDatastoreType.CONFIGURATION, bridgeEntryIid);
@@ -213,7 +224,8 @@ public class TunnelInterfaceConfigurationTest {
         doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
                 LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
 
-        updateHelper.updateConfiguration(dataBroker,idManager,tunnelInterfaceDisabled,tunnelInterfaceEnabled);
+        updateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager, mdsalApiManager,
+                tunnelInterfaceDisabled,tunnelInterfaceEnabled);
 
         //verify whether operational data store is updated with the new oper state.
         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
@@ -234,7 +246,8 @@ public class TunnelInterfaceConfigurationTest {
         doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
                 LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
 
-        updateHelper.updateConfiguration(dataBroker,idManager,tunnelInterfaceEnabled,tunnelInterfaceDisabled);
+        updateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager, mdsalApiManager,
+                tunnelInterfaceEnabled,tunnelInterfaceDisabled);
 
         //verify whether operational data store is updated with the new oper state.
         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
index 4b7adb0f5bd69e251119bba4abef7042d65d2b8d..469ac2a5c14de190f6ae65be0902e115d7b43913 100644 (file)
@@ -33,11 +33,13 @@ import org.opendaylight.idmanager.IdManager;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 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.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -46,11 +48,13 @@ public class VlanInterfaceConfigurationTest {
 
     @Mock
     DataBroker dataBroker;
+    @Mock
+    AlivenessMonitorService alivenessMonitorService;
     @Mock IdManager idManager;
     @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
     @Mock ReadOnlyTransaction mockReadTx;
     @Mock WriteTransaction mockWriteTx;
-
+    @Mock IMdsalApiManager mdsalApiManager;
     OvsInterfaceConfigAddHelper addHelper;
     OvsInterfaceConfigRemoveHelper removeHelper;
 
@@ -103,7 +107,8 @@ public class VlanInterfaceConfigurationTest {
         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
                LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
 
-        addHelper.addConfiguration(dataBroker, null, vlanInterfaceEnabled, idManager);
+        addHelper.addConfiguration(dataBroker, null, vlanInterfaceEnabled, idManager,
+                alivenessMonitorService, mdsalApiManager);
 
         //Nothing to verify, since when switch is not connected we don't do any datastore operation
 
@@ -119,7 +124,8 @@ public class VlanInterfaceConfigurationTest {
         doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
                 LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
 
-        addHelper.addConfiguration(dataBroker, null, vlanInterfaceEnabled, idManager);
+        addHelper.addConfiguration(dataBroker, null, vlanInterfaceEnabled, idManager,
+                alivenessMonitorService, mdsalApiManager);
 
         //Nothing to verify, since when adminstate is enabled and switch opstate is already up,
         //we don't do any datastore operation
@@ -141,7 +147,8 @@ public class VlanInterfaceConfigurationTest {
         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(vlanInterfaceEnabled.getName()));
         stateInterface = ifaceBuilder.build();
 
-        addHelper.addConfiguration(dataBroker, null, vlanInterfaceDisabled, idManager);
+        addHelper.addConfiguration(dataBroker, null, vlanInterfaceDisabled, idManager,
+                alivenessMonitorService, mdsalApiManager);
 
         //verification
         verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier, stateInterface);
@@ -164,7 +171,8 @@ public class VlanInterfaceConfigurationTest {
         ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(vlanInterfaceEnabled.getName()));
         stateInterface = ifaceBuilder.build();
 
-        removeHelper.removeConfiguration(dataBroker, vlanInterfaceEnabled, idManager, null);
+        removeHelper.removeConfiguration(dataBroker,alivenessMonitorService, vlanInterfaceEnabled, idManager,
+                mdsalApiManager, null);
 
         //verification
         verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier, stateInterface);
index 3535c435e9c0297c2fde7e5fe7006efecfc88739..d581347d55a1ea0bcc91f2dc27c5e94106120cbd 100644 (file)
@@ -53,6 +53,7 @@ public interface IMdsalApiManager {
      * @param delayTime
      */
     public void syncRemoveFlow(FlowEntity flowEntity, long delayTime);
+    public void syncInstallFlow(FlowEntity flowEntity, long delayTime);
 
     /**
      * API to install the Group on Data Plane Node synchronously. It internally waits for
index c617cfcda7feb7b1fc7318e11261e9acfe34be63..cacb6344bd1ca8bcff135f8f20a9d3e9addb3d11 100644 (file)
@@ -130,6 +130,11 @@ public class MDSALUtilProvider implements BindingAwareConsumer, IMdsalApiManager
         mdSalMgr.syncSetUpFlow(flowEntity,  delayTime, true);
     }
 
+    @Override
+    public void syncInstallFlow(FlowEntity flowEntity, long delayTime) {
+        mdSalMgr.syncSetUpFlow(flowEntity, delayTime, false);
+    }
+
     @Override
     public void syncInstallGroup(GroupEntity groupEntity, long delayTime) {
         mdSalMgr.syncSetUpGroup(groupEntity, delayTime, false);
index cced35d54575ba854650c04c87dc2bba51809a1a..dcae6c67445083d05c7c84248ef12f2df376665a 100644 (file)
@@ -5,6 +5,7 @@ module bgp {
 
   import ietf-inet-types {
     prefix inet;
+    revision-date "2010-09-24";
   }
   import ietf-yang-types {
     prefix yang;
index 4611809073dfd5de7220b6addc8059df3c39fb8b..54020fc988b69f7d8109f36374210e6cf6e0a581 100644 (file)
@@ -8,7 +8,7 @@ module ebgp {
   prefix "ericsson-bgp";
 
   // import some basic inet types
-  import ietf-inet-types { prefix inet; }
+  import ietf-inet-types { prefix inet; revision-date "2010-09-24"; }
 
   // meta
   organization
@@ -83,7 +83,6 @@ module ebgp {
     container ebgp-multihop {
       leaf nhops {
         type uint32;
-        mandatory "true";
       }
       leaf peer-ip {
         type leafref {
index 6ecdd0330fd9f6e8aa8d962c6eff37eb0bb99680..c4afd3488bcd1819fa8bb2912f8e8c31a405f847 100644 (file)
@@ -25,7 +25,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <dependency>
             <groupId>org.opendaylight.mdsal</groupId>
             <artifactId>yang-binding</artifactId>
-            <version>${yangtools.version}</version>
+            <version>${mdsal.model.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
index 4001339b2deae77901260082418f43b55965da3a..922a727b26f61d382984537aad10a025db9fbff3 100644 (file)
@@ -37,6 +37,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <artifactId>vpnmanager-api</artifactId>
             <version>${vpnservices.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.vpnservice</groupId>
+            <artifactId>elanmanager-api</artifactId>
+            <version>${vpnservices.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.vpnservice</groupId>
             <artifactId>mdsalutil-api</artifactId>
index 1e0252b028b54c536fa006857aa2b77c9c3e602a..4a474f35bcc6dc8965e5c487b44dc338b0ab0836 100644 (file)
@@ -14,6 +14,11 @@ import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
@@ -70,6 +75,8 @@ public class NeutronNetworkChangeListener extends AbstractDataChangeListener<Net
         if (LOG.isTraceEnabled()) {
             LOG.trace("Adding Network : key: " + identifier + ", value=" + input);
         }
+        //Create ELAN instance for this network
+        createElanInstance(input.getUuid().getValue());
     }
 
     @Override
@@ -77,6 +84,8 @@ public class NeutronNetworkChangeListener extends AbstractDataChangeListener<Net
         if (LOG.isTraceEnabled()) {
             LOG.trace("Removing Network : key: " + identifier + ", value=" + input);
         }
+        //Delete ELAN instance for this network
+        deleteElanInstance(input.getUuid().getValue());
     }
 
     @Override
@@ -87,4 +96,19 @@ public class NeutronNetworkChangeListener extends AbstractDataChangeListener<Net
         }
     }
 
+    private void createElanInstance(String elanInstanceName) {
+        ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setKey(new
+                ElanInstanceKey(elanInstanceName)).build();
+        InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
+                .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+        MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInstance);
+
+    }
+
+    private void deleteElanInstance(String elanInstanceName) {
+        InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
+                .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+        MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
+    }
+
 }
index 3783a61ba6f3ae60c904a4e57b00fa271d63c64f..e43c34c243c17d733b35f18ed3a52735b03b25e4 100644 (file)
@@ -19,11 +19,16 @@ import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
 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.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.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.neutron.ports.rev150712.port.attributes.FixedIps;
 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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
         .PortFixedipToPortNameBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
@@ -123,6 +128,8 @@ public class NeutronPortChangeListener extends AbstractDataChangeListener<Port>
         int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
         // Create of-port interface for this neutron port
         createOfPortInterface(port, portVlanId);
+        LOG.debug("Creating ELAN Interface");
+        createElanInterface(port, portVlanId);
         LOG.debug("Add port to subnet");
         // add port to local Subnets DS
         Uuid vpnId = addPortToSubnets(port);
@@ -147,6 +154,7 @@ public class NeutronPortChangeListener extends AbstractDataChangeListener<Port>
         }
         int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
         // Remove of-port interface for this neutron port
+        // ELAN interface is also implicitly deleted as part of this operation
         deleteOfPortInterface(port, portVlanId);
 
     }
@@ -220,6 +228,22 @@ public class NeutronPortChangeListener extends AbstractDataChangeListener<Port>
                 .getUuid());
     }
 
+    private void createElanInterface(Port port, int portVlanId) {
+        String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
+        String interfaceName = new StringBuilder(name).append(":").append(Integer.toString(portVlanId)).toString();
+        String elanInstanceName = port.getNetworkId().getValue();
+        List<PhysAddress> physAddresses = new ArrayList<>();
+        physAddresses.add(new PhysAddress(port.getMacAddress()));
+
+        InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
+                .class, new ElanInterfaceKey(interfaceName)).build();
+        ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
+                .setName(interfaceName).setStaticMacEntries(physAddresses).
+                        setKey(new ElanInterfaceKey(interfaceName)).build();
+        MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInterface);
+        LOG.debug("Creating new ELan Interface {}", elanInterface);
+    }
+
     // adds port to subnet list and creates vpnInterface
     private Uuid addPortToSubnets(Port port) {
         Uuid subnetId = null;
index 826f9f839b52a35c0082c336f631031fe79ff456..4cd576e2ac9355f95cde2d4153c3f2b962bd646b 100644 (file)
@@ -18,7 +18,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.router
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -83,21 +82,16 @@ public class NeutronRouterChangeListener extends AbstractDataChangeListener<Rout
         if (LOG.isTraceEnabled()) {
             LOG.trace("Removing router : key: " + identifier + ", value=" + input);
         }
-        // check if this router has internal-VPN
         Uuid routerId = input.getUuid();
-        VpnMap vpnmap = NeutronvpnUtils.getVpnMap(broker, routerId);
-        if (vpnmap != null) {
-            // if yes, remove corresponding internal vpn
-            LOG.trace("removing internal-vpn for router {}", routerId);
-            nvpnManager.removeL3Vpn(routerId);
-        } else {
-            // if not, it is associated with some VPN
-            // remove VPN-router association
-            Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId);
-            LOG.trace("dissociating router {} from vpn {}", routerId, vpnId);
-            nvpnManager.dissociateRouterFromVpn(vpnId, routerId);
+        // fetch subnets associated to router
+        List<Interfaces> routerInterfaces = input.getInterfaces();
+        List<Uuid> routerSubnetIds = new ArrayList<Uuid>();
+        if (routerInterfaces != null) {
+            for (Interfaces rtrIf : routerInterfaces) {
+                routerSubnetIds.add(rtrIf.getSubnetId());
+            }
         }
-
+        nvpnManager.handleNeutronRouterDeleted(routerId, routerSubnetIds);
     }
 
     @Override
@@ -107,7 +101,11 @@ public class NeutronRouterChangeListener extends AbstractDataChangeListener<Rout
                     update);
         }
         Uuid routerId = update.getUuid();
-        Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId);
+        Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
+        // internal vpn always present in case external vpn not found
+        if (vpnId == null) {
+            vpnId = routerId;
+        }
         List<Interfaces> oldInterfaces = (original.getInterfaces() != null) ? original.getInterfaces() : new
                 ArrayList<Interfaces>();
         List<Interfaces> newInterfaces = (update.getInterfaces() != null) ? update.getInterfaces() : new
index a94101d0fb0328d15fb59cb7794d6eb09319c486..e7399566f514e9b6b0ce04880bf7854c76f548d3 100644 (file)
@@ -369,10 +369,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
             return;
         }
         String portname = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
-        String name = new StringBuilder(portname).append(":0").toString();
         List<Adjacency> adjList = new ArrayList<Adjacency>();
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
-                child(VpnInterface.class, new VpnInterfaceKey(name)).build();
+                child(VpnInterface.class, new VpnInterfaceKey(portname)).build();
         // find router associated to vpn
         Uuid routerId = NeutronvpnUtils.getRouterforVpn(broker, vpnId);
         Router rtr = null;
@@ -392,7 +391,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
             // create extra route adjacency
             if (rtr != null && rtr.getRoutes() != null) {
                 List<String> routeList = rtr.getRoutes();
-                List<Adjacency> erAdjList = addAdjacencyforExtraRoute(routeList, false, name);
+                List<Adjacency> erAdjList = addAdjacencyforExtraRoute(routeList, false, portname);
                 if (erAdjList != null) {
                     adjList.addAll(erAdjList);
                 }
@@ -400,18 +399,18 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
         }
         // create vpn-interface on this neutron port
         Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
-        VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(name)).
-                setName(name).setVpnInstanceName(vpnId.getValue()).addAugmentation(Adjacencies.class, adjs);
+        VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(portname)).
+                setName(portname).setVpnInstanceName(vpnId.getValue()).addAugmentation(Adjacencies.class, adjs);
         VpnInterface vpnIf = vpnb.build();
 
-        NeutronvpnUtils.lockVpnInterface(lockManager, name);
+        NeutronvpnUtils.lockVpnInterface(lockManager, portname);
         try {
             logger.debug("Creating vpn interface {}", vpnIf);
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
         } catch (Exception ex) {
-            logger.error("Creation of vpninterface {} failed due to {}", name, ex);
+            logger.error("Creation of vpninterface {} failed due to {}", portname, ex);
         } finally {
-            NeutronvpnUtils.unlockVpnInterface(lockManager, name);
+            NeutronvpnUtils.unlockVpnInterface(lockManager, portname);
         }
     }
 
@@ -419,18 +418,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
 
         if (port != null) {
             String pname = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
-            String name = new StringBuilder(pname).append(":0").toString();
             InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
-                    child(VpnInterface.class, new VpnInterfaceKey(name)).build();
+                    child(VpnInterface.class, new VpnInterfaceKey(pname)).build();
 
-            NeutronvpnUtils.lockVpnInterface(lockManager, name);
+            NeutronvpnUtils.lockVpnInterface(lockManager, pname);
             try {
-                logger.debug("Deleting vpn interface {}", name);
+                logger.debug("Deleting vpn interface {}", pname);
                 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
             } catch (Exception ex) {
-                logger.error("Deletion of vpninterface {} failed due to {}", name, ex);
+                logger.error("Deletion of vpninterface {} failed due to {}", pname, ex);
             } finally {
-                NeutronvpnUtils.unlockVpnInterface(lockManager, name);
+                NeutronvpnUtils.unlockVpnInterface(lockManager, pname);
             }
         }
     }
@@ -689,30 +687,29 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
                     String destination = parts[1];
 
                     String tapPortName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
-                    String ifname = new StringBuilder(tapPortName).append(":0").toString();
                     logger.trace("Adding extra route with nexthop {}, destination {}, ifName {}", nextHop,
-                            destination, ifname);
+                            destination, tapPortName);
                     Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination).setNextHopIp(nextHop).setKey
                             (new AdjacencyKey(destination)).build();
                     if (rtrUp == false) {
-                        if (ifname.equals(vpnifname)) {
+                        if (tapPortName.equals(vpnifname)) {
                             adjList.add(erAdj);
                         }
                         continue;
                     }
                     InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
-                            child(VpnInterface.class, new VpnInterfaceKey(ifname)).build();
+                            child(VpnInterface.class, new VpnInterfaceKey(tapPortName)).build();
                     Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(broker, LogicalDatastoreType
                             .CONFIGURATION, vpnIfIdentifier);
                     if (optionalVpnInterface.isPresent()) {
                         Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(erAdj)).build();
-                        VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(ifname))
+                        VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(tapPortName))
                                 .addAugmentation(Adjacencies.class, erAdjs).build();
                         MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
                         logger.trace("extra route {} added successfully", route);
                     } else {
                         logger.error("VM adjacency for interface {} not present ; cannot add extra route adjacency",
-                                ifname);
+                                tapPortName);
                     }
                 } else {
                     logger.error("Incorrect input received for extra route. {}", parts);
@@ -735,11 +732,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
                     String destination = parts[1];
 
                     String tapPortName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
-                    String ifname = new StringBuilder(tapPortName).append(":0").toString();
                     logger.trace("Removing extra route with nexthop {}, destination {}, ifName {}", nextHop,
-                            destination, ifname);
+                            destination, tapPortName);
                     InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
-                            child(VpnInterface.class, new VpnInterfaceKey(ifname)).augmentation(Adjacencies.class)
+                            child(VpnInterface.class, new VpnInterfaceKey(tapPortName)).augmentation(Adjacencies.class)
                             .child(Adjacency.class, new AdjacencyKey(destination)).build();
                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
                     logger.trace("extra route {} deleted successfully", route);
@@ -758,7 +754,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
     }
 
     protected void removeL3Vpn(Uuid id) {
-        // read VPN networks
+        // read VPNMaps
         VpnMap vpnMap = NeutronvpnUtils.getVpnMap(broker, id);
         Uuid router = vpnMap.getRouterId();
         // dissociate router
@@ -800,39 +796,40 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
         }
     }
 
-    protected void associateRouterToVpn(Uuid vpn, Uuid router) {
+    protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
 
-        // remove existing Router-VPN
-        if (!vpn.equals(router)) {
-            removeL3Vpn(router);
-        }
-        updateVpnMaps(vpn, null, router, null, null);
+        List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, routerId);
 
-        List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, router);
-        logger.debug("Adding subnets...");
+        if (!vpnId.equals(routerId)) {
+            logger.debug("Removing subnets from internal vpn {}", routerId.getValue());
+            if (routerSubnets != null) {
+                for (Uuid subnet : routerSubnets) {
+                    removeSubnetFromVpn(routerId, subnet);
+                }
+            }
+        }
+        logger.debug("Adding subnets to vpn {}", vpnId.getValue());
         for (Uuid subnet : routerSubnets) {
-            addSubnetToVpn(vpn, subnet);
+            addSubnetToVpn(vpnId, subnet);
         }
+
+        updateVpnMaps(vpnId, null, routerId, null, null);
     }
 
-    protected void dissociateRouterFromVpn(Uuid vpn, Uuid router) {
-        clearFromVpnMaps(vpn, router, null);
+    protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
 
-        // fetching sn from SubnetmapDS for internal VPN because sn already deleted from RouterIf DS on router deletion
-        List<Uuid> routerSubnets = (vpn.equals(router)) ? getSubnetsforVpn(vpn) :
-                NeutronvpnUtils.getNeutronRouterSubnetIds(broker, router);
+        // remove existing external vpn interfaces
+        List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, routerId);
 
-        logger.debug("dissociateRouter vpn {} router {} Removing subnets...", vpn.getValue(), router.getValue());
         if (routerSubnets != null) {
             for (Uuid subnet : routerSubnets) {
-                removeSubnetFromVpn(vpn, subnet);
+                logger.debug("Removing subnets from external vpn {}", vpnId.getValue());
+                removeSubnetFromVpn(vpnId, subnet);
+                logger.debug("Adding subnets to internal vpn {}", routerId.getValue());
+                addSubnetToVpn(routerId, subnet);
             }
         }
-        // create Router-VPN for this router
-        if (!vpn.equals(router)) {
-            logger.debug("Re-creating vpn-router...");
-            createL3Vpn(router, null, null, null, null, null, router, null);
-        }
+        clearFromVpnMaps(vpnId, routerId, null);
     }
 
     protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
@@ -1056,6 +1053,28 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
         return result;
     }
 
+    protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
+        // check if the router is associated to some VPN
+        Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
+        if (vpnId != null) {
+            // remove existing external vpn interfaces
+            for (Uuid subnetId : routerSubnetIds) {
+                removeSubnetFromVpn(vpnId, subnetId);
+            }
+            clearFromVpnMaps(vpnId, routerId, null);
+        } else {
+            // remove existing internal vpn interfaces
+            for (Uuid subnetId : routerSubnetIds) {
+                removeSubnetFromVpn(routerId, subnetId);
+            }
+        }
+        // delete entire vpnMaps node for internal VPN
+        deleteVpnMapsNode(routerId);
+
+        // delete vpn-instance for internal VPN
+        deleteVpnInstance(routerId);
+    }
+
     protected Subnet getNeutronSubnet(Uuid subnetId) {
         InstanceIdentifier<Subnet> inst = InstanceIdentifier.create(Neutron.class).
                 child(Subnets.class).child(Subnet.class, new SubnetKey(subnetId));
index 042b0ea19f28dd22f0e400f892d715692b59c79b..a74a34b62a65303df327f79c57c79bd82a3b2635 100644 (file)
@@ -25,6 +25,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey;
 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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TimeUnits;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInput;
@@ -104,16 +107,26 @@ public class NeutronvpnUtils {
         return null;
     }
 
-    protected static Uuid getVpnForRouter(DataBroker broker, Uuid router) {
+    // true for external vpn, false for internal vpn
+    protected static Uuid getVpnForRouter(DataBroker broker, Uuid routerId, Boolean externalVpn) {
         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
-        Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
+        Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
+                vpnMapsIdentifier);
         if (optionalVpnMaps.isPresent()) {
             VpnMaps vpnNets = optionalVpnMaps.get();
             List<VpnMap> allMaps = vpnNets.getVpnMap();
-            if (router != null) {
+            if (routerId != null) {
                 for (VpnMap vpnMap : allMaps) {
-                    if (router.equals(vpnMap.getRouterId())) {
-                        return vpnMap.getVpnId();
+                    if (routerId.equals(vpnMap.getRouterId())) {
+                        if (externalVpn == true) {
+                            if (!routerId.equals(vpnMap.getVpnId())) {
+                                return vpnMap.getVpnId();
+                            }
+                        } else {
+                            if (routerId.equals(vpnMap.getVpnId())) {
+                                return vpnMap.getVpnId();
+                            }
+                        }
                     }
                 }
             }
@@ -201,20 +214,20 @@ public class NeutronvpnUtils {
     protected static List<Uuid> getNeutronRouterSubnetIds(DataBroker broker, Uuid routerId) {
         logger.info("getNeutronRouterSubnetIds for {}", routerId.getValue());
 
-        List<Uuid> subnetNames = new ArrayList<Uuid>();
+        List<Uuid> subnetIdList = new ArrayList<Uuid>();
         Router router = getNeutronRouter(broker, routerId);
         if (router != null) {
             List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router
-                    .Interfaces> ifs = router.getInterfaces();
-            if (!ifs.isEmpty()) {
+                    .Interfaces> interfacesList = router.getInterfaces();
+            if (!interfacesList.isEmpty()) {
                 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers
-                        .router.Interfaces iff : ifs) {
-                    subnetNames.add(iff.getSubnetId());
+                        .router.Interfaces interfaces : interfacesList) {
+                    subnetIdList.add(interfaces.getSubnetId());
                 }
             }
         }
         logger.info("returning from getNeutronRouterSubnetIds for {}", routerId.getValue());
-        return subnetNames;
+        return subnetIdList;
     }
 
     protected static String uuidToTapPortName(Uuid id) {
@@ -261,17 +274,10 @@ public class NeutronvpnUtils {
         try {
             Uuid subnetUUID = port.getFixedIps().get(0).getSubnetId();
 
-            org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets
-                    .SubnetKey subnetkey = new org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets
-                    .rev150712.subnets.attributes.subnets.SubnetKey(subnetUUID);
-            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets
-                    .attributes.subnets.Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class).child(org
-                    .opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets
-                    .class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets
-                    .attributes.subnets.Subnet.class, subnetkey);
-            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes
-                    .subnets.Subnet> subnet = read(broker, LogicalDatastoreType.CONFIGURATION, subnetidentifier);
-
+            SubnetKey subnetkey = new SubnetKey(subnetUUID);
+            InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class).child(Subnets
+                    .class).child(Subnet.class, subnetkey);
+            Optional<Subnet> subnet = read(broker, LogicalDatastoreType.CONFIGURATION,subnetidentifier);
             if (subnet.isPresent()) {
                 cidr = subnet.get().getCidr();
                 // Extract the prefix length from cidr
diff --git a/pom.xml b/pom.xml
index 591652c614cb313d9f3b8aa5a043e71584839235..e29557e99b9cce51a66757b8a4c7e0bf4d871739 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -4,8 +4,7 @@ Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others.  A
 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 INTERNAL
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <groupId>org.opendaylight.vpnservice</groupId>
   <artifactId>vpnservice</artifactId>
   <version>0.3.0-SNAPSHOT</version>
@@ -35,6 +34,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <module>distribution/karaf</module>
     <module>features</module>
     <module>vpnservice-artifacts</module>
+    <module>vpnintent</module>
   </modules>
 
   <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
@@ -62,4 +62,4 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <url>https://wiki.opendaylight.org/view/VPNService:Main</url>
     <tag>HEAD</tag>
   </scm>
-</project>
+</project>
\ No newline at end of file
diff --git a/vpnintent/api/pom.xml b/vpnintent/api/pom.xml
new file mode 100644 (file)
index 0000000..24f8d54
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.opendaylight.vpnservice</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>0.3.0-SNAPSHOT</version>
+    <relativePath>../../commons/binding-parent</relativePath>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.vpnservice</groupId>
+  <artifactId>vpnintent-api</artifactId>
+  <version>${vpnservices.version}</version>
+  <packaging>bundle</packaging>
+
+  <dependencies>
+  <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-inet-types</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-yang-types</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/vpnintent/api/src/main/yang/vpnintent.yang b/vpnintent/api/src/main/yang/vpnintent.yang
new file mode 100644 (file)
index 0000000..f0884e4
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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 INTERNAL
+ */
+module vpnintent {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:vpnintent";
+    prefix "vpnintent";
+
+    import ietf-inet-types { prefix inet; revision-date 2010-09-24;}
+
+    revision "2015-01-05" {
+        description "Initial revision of VPN intent model.
+            Create VPN via Intent, keep VPN state and manage MPLS labels";
+    }
+
+    container vpns{
+        list vpn-intents {
+            key "vpn-name";
+            uses vpn-intent;
+        }
+    }
+
+    typedef failover-type {
+        type enumeration {
+            enum fast-reroute {
+                value 1;
+            }
+            enum slow-reroute {
+                value 2;
+            }
+        }
+    }
+
+    grouping vpn-intent {
+        leaf vpn-name {
+            type string;
+            description "VPN name";
+            mandatory true;
+        }
+        leaf path-protection {
+            type boolean;
+        }
+        leaf failover-type {
+            type failover-type;
+        }
+        list endpoint {
+            key "site-name";
+            uses endpoint-fields;
+            description "List to keep track site name and endpoint.";
+          }
+    }
+
+    grouping endpoint-fields {
+        leaf site-name{
+            type string;
+            description "VPN member site name.";
+        }
+
+        leaf ip-prefix {
+            type inet:ip-prefix;
+            description "VPN member IP prefix.";
+        }
+
+        leaf switch-port-id {
+            type string;
+            description "Switch and port ID that VPN member is connected to.";
+        }
+    }
+
+    grouping labels {
+        list label {
+            key "label-id";
+            leaf "label-id"{
+                type uint32 {
+                    range "0 .. 524288";
+                }
+                description "20 bit MPLS label ID";
+                mandatory true;
+            }
+            uses endpoint-fields;
+            description "Keep track of MPLS/other label endpoint relation.";
+        }
+     }
+
+    container mpls-labels {
+        uses labels;
+    }
+
+    rpc add-vpn-endpoint{
+        description
+            "Add VPN endpoint.";
+        input {
+            leaf vpn-name {
+                type string;
+                description "VPN name";
+                mandatory true;
+            }
+            uses endpoint-fields;
+        }
+    }
+
+    rpc remove-vpn-endpoint{
+        description
+            "Remove VPN endpoint.";
+        input {
+            leaf vpn-name {
+                type string;
+                description "VPN name";
+                mandatory true;
+            }
+            leaf site-name{
+                type string;
+                description "VPN member site name.";
+            }
+        }
+    }
+
+    rpc remove-vpn{
+        description
+            "Remove VPN and its endpoints.";
+        input {
+            leaf vpn-name {
+                type string;
+                description "VPN name";
+                mandatory true;
+            }
+        }
+    }
+  }
diff --git a/vpnintent/impl/pom.xml b/vpnintent/impl/pom.xml
new file mode 100644 (file)
index 0000000..f69f9c8
--- /dev/null
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <parent>
+    <groupId>org.opendaylight.vpnservice</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.3.0-SNAPSHOT</version>
+    <relativePath>../../commons/config-parent</relativePath>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>vpnintent-impl</artifactId>
+  <version>${vpnservices.version}</version>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <nic.version>1.2.0-SNAPSHOT</nic.version>
+    <powermock.version>1.5.2</powermock.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vpnintent-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <!-- NIC dependency -->
+    <dependency>
+      <groupId>org.opendaylight.nic</groupId>
+      <artifactId>intent-api</artifactId>
+      <version>${nic.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.nic</groupId>
+      <artifactId>intent-mapping-interface</artifactId>
+      <version>${nic.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.nic</groupId>
+      <artifactId>utils</artifactId>
+      <version>${nic.version}</version>
+    </dependency>
+
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+</project>
diff --git a/vpnintent/impl/src/main/config/default-config.xml b/vpnintent/impl/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..0b6f6a6
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2016 Inocybe Technologies 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
+-->
+<snapshot>
+  <required-capabilities>
+      <capability>urn:opendaylight:params:xml:ns:yang:vpnintent:impl?module=vpnintent-impl&amp;revision=2014-12-10</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+  </required-capabilities>
+  <configuration>
+
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:vpnintent:impl">prefix:vpnintent-impl</type>
+          <name>vpnintent-impl-default</name>
+          <broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <name>binding-osgi-broker</name>
+          </broker>
+          <rpc-registry>
+              <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+              <name>binding-rpc-broker</name>
+          </rpc-registry>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+</snapshot>
diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java
new file mode 100644 (file)
index 0000000..5fe2466
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.constraints.rev150122.FailoverType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Actions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Constraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Subjects;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.SubjectsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.allow.AllowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.block.BlockBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.failover.constraint.FailoverConstraintBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.protection.constraint.ProtectionConstraintBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * This class is used to build Intents object and
+ * write it to Network Intent Composition md-sal tree
+ * in order to create/delete intents between two endpoint groups.
+ */
+public class IntentServiceManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(IntentServiceManager.class);
+    private static final short FIRST_SUBJECT = 1;
+    private static final short SECOND_SUBJECT = 2;
+    public static final String ACTION_ALLOW = "ALLOW";
+    public static final String ACTION_BLOCK = "BLOCK";
+    public static final String FAST_REROUTE = "fast-reroute";
+    public static final String SLOW_REROUTE = "slow-reroute";
+    private final DataBroker dataBroker;
+    private static final InstanceIdentifier<Intents> INTENTS_IID = IidFactory.getIntentsIid();
+    private final MdsalUtils mdsal;
+
+    public IntentServiceManager(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+        this.mdsal = new MdsalUtils(dataBroker);
+    }
+
+    /**
+     * Create Intents object and write to to config tree to trigger intents
+     * @param src :Source Site Name
+     * @param dst :Destination Site Name
+     * @param intentAction :Intent verb: ALLOW or BLOCK
+     * @param failOverType
+     */
+    public void addIntent(String src, String dst, String intentAction, String failOverType) {
+        Preconditions.checkNotNull(src);
+        Preconditions.checkNotNull(dst);
+        Preconditions.checkNotNull(intentAction);
+
+        List<Intent> intentList = null;
+        List<Subjects> subjects = createSubjects(dst, src);
+        List<Actions> intentActions = createActions(intentAction);
+        List<Constraints> intentConstraints = createConstraints(failOverType);
+
+        Intent intent  = new IntentBuilder().setId(new Uuid(UUID.randomUUID().toString()))
+                .setSubjects(subjects).setActions(intentActions)
+                .setConstraints(intentConstraints)
+                .build();
+
+        Intents currentIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, INTENTS_IID);
+        if (currentIntents == null) {
+            intentList = new ArrayList<>();
+        } else {
+            intentList = currentIntents.getIntent();
+        }
+        intentList.add(intent);
+        Intents intents = new IntentsBuilder().setIntent(intentList).build();
+        mdsal.put(LogicalDatastoreType.CONFIGURATION, INTENTS_IID, intents);
+        LOG.info("AddIntent: config populated: {}", intents);
+    }
+
+    /**
+     * Delete an Intent
+     * @param id :Uuid of the Intent to be deleted
+     */
+    public void removeIntent(Uuid id) {
+        Preconditions.checkNotNull(id);
+        InstanceIdentifier<Intent> iid = InstanceIdentifier.create(Intents.class).child(Intent.class, new IntentKey(id));
+        mdsal.delete(LogicalDatastoreType.CONFIGURATION, iid);
+        LOG.info("RemoveIntent succeeded");
+    }
+
+    /**
+     * Remove all associated intents by endpointGroupName
+     * @param endpointGroupName
+     */
+    public void removeIntentsByEndpoint(String endpointGroupName) {
+        Preconditions.checkNotNull(endpointGroupName);
+
+        Intents intents = mdsal.read(LogicalDatastoreType.CONFIGURATION, INTENTS_IID);
+
+        if (intents != null && intents.getIntent() != null) {
+            for (Intent intent : intents.getIntent()) {
+                if (intent.getSubjects() != null && intent.getSubjects().size() > 0) {
+                    String endpointValue = "";
+                    for (Subjects subject : intent.getSubjects()) {
+                        if (subject
+                                .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup) {
+                            org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup) subject
+                                    .getSubject();
+                            endpointValue = epg.getEndPointGroup().getName();
+                        } else if (subject
+                                .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector) {
+                            org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector) subject
+                                    .getSubject();
+                            endpointValue = epg.getEndPointSelector().getEndPointSelector();
+                        } else if (subject
+                                .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector) {
+                            org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector) subject
+                                    .getSubject();
+                            endpointValue = epg.getEndPointGroupSelector().getEndPointGroupSelector();
+                        }
+                        if (endpointValue.equalsIgnoreCase(endpointGroupName)) {
+                            removeIntent(intent.getId());
+                            LOG.info("Deleted Intent ID : {} for endpoint: {}", intent.getId(), endpointGroupName);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Create a list of Intent actions
+     * @param intentAction
+     * @return :a list of Actions
+     */
+    private List<Actions> createActions(String intentAction) {
+        List<Actions> actionsList = new ArrayList<Actions>();
+        short order = 1;
+        org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.Action action = null;
+        if (intentAction.equalsIgnoreCase(ACTION_ALLOW)) {
+            action = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action
+                    .AllowBuilder().setAllow(new AllowBuilder().build()).build();
+        } else if (intentAction.equalsIgnoreCase(ACTION_BLOCK)) {
+            action = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action
+                    .BlockBuilder().setBlock(new BlockBuilder().build()).build();
+        }
+
+        Actions intentActions = new ActionsBuilder().setOrder(order).setAction(action).build();
+        actionsList.add(intentActions);
+        return actionsList;
+    }
+
+    /**
+     * Create a list of Intent subjects
+     * @param src :Source Site Name
+     * @param dst :Destination Site Name
+     * @return :a list of Subjects
+     */
+    private List<Subjects> createSubjects(String src, String dst) {
+        List<Subjects> subjectList = new ArrayList<Subjects>();
+
+        EndPointGroup endpointGroupFrom = new EndPointGroupBuilder().setName(src).build();
+        org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup fromEPG =
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject
+                .EndPointGroupBuilder().setEndPointGroup(endpointGroupFrom).build();
+        Subjects subjects1 = new SubjectsBuilder().setOrder(FIRST_SUBJECT).setSubject(fromEPG).build();
+
+        EndPointGroup endpointGroupTo = new EndPointGroupBuilder().setName(dst).build();
+        org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup toEPG =
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject
+                .EndPointGroupBuilder().setEndPointGroup(endpointGroupTo).build();
+        Subjects subjects2 = new SubjectsBuilder().setOrder(SECOND_SUBJECT).setSubject(toEPG).build();
+
+        subjectList.add(subjects1);
+        subjectList.add(subjects2);
+        return subjectList;
+    }
+
+    /**
+     * Create a list of Intent constraints
+     * @param failOverType :Type of failover, fast-reroute or slow-reroute
+     * @return
+     */
+    private List<Constraints> createConstraints(String failOverType) {
+        List<Constraints> intentConstraints = new ArrayList<Constraints>();
+        if (failOverType==null) {
+            return intentConstraints;
+        }
+        short order = 1;
+        org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints
+            protectionConstraint = null;
+        org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints
+            failoverConstraint = null;
+        if (failOverType.equals(FAST_REROUTE)) {
+            protectionConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent
+                    .constraints.constraints.ProtectionConstraintBuilder()
+                    .setProtectionConstraint(new ProtectionConstraintBuilder().setIsProtected(true).build()).build();
+            failoverConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints
+                    .constraints.FailoverConstraintBuilder()
+                    .setFailoverConstraint(new FailoverConstraintBuilder().setFailoverSelector(FailoverType.FastReroute).build())
+                    .build();
+        } else if (failOverType.equals(SLOW_REROUTE)) {
+            protectionConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent
+                    .constraints.constraints.ProtectionConstraintBuilder()
+                    .setProtectionConstraint(new ProtectionConstraintBuilder().setIsProtected(true).build()).build();
+            failoverConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints
+                    .constraints.FailoverConstraintBuilder()
+                    .setFailoverConstraint(new FailoverConstraintBuilder().setFailoverSelector(FailoverType.SlowReroute).build())
+                    .build();
+        }
+        Constraints constraint1 = new ConstraintsBuilder().setOrder(order).setConstraints(protectionConstraint).build();
+        Constraints constraint2 = new ConstraintsBuilder().setOrder(++order).setConstraints(failoverConstraint).build();
+        intentConstraints.add(constraint1);
+        intentConstraints.add(constraint2);
+        return intentConstraints;
+    }
+}
diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MappingServiceManager.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MappingServiceManager.java
new file mode 100644 (file)
index 0000000..4ef274e
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.nic.mapping.api.IntentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class MappingServiceManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MappingServiceManager.class);
+    private IntentMappingService intentMappingService;
+    private String IP_PREFIX_PROPERTY = "ip_prefix";
+    private String SWITCH_PORT_ID_PROPERTY = "switch_port";
+    private String MPLS_LABEL_PROPERTY = "mpls_label";
+    private String NEXT_HOP_PROPERTY = "next_hop";
+
+    public MappingServiceManager(IntentMappingService intentMappingService) {
+        Preconditions.checkNotNull(intentMappingService);
+        this.intentMappingService = intentMappingService;
+    }
+
+    /**
+     * @param siteName
+     *            Name of the member
+     * @param ipPrefix
+     *            Ip prefix of the member
+     * @param switchPortId
+     *            Switch ID and port ID (i.e. openflow:1:2)
+     * @param mplsLabel
+     *            MPLS label, if needed
+     * @param nextHop
+     *            Next hop in the route
+     */
+    public void add(final String siteName, final String ipPrefix, final String switchPortId, final Long mplsLabel,
+            final String nextHop) {
+        Preconditions.checkNotNull(siteName);
+        Preconditions.checkNotNull(ipPrefix);
+        Preconditions.checkNotNull(switchPortId);
+
+        Map<String, String> objs = new HashMap<>();
+        objs.put(IP_PREFIX_PROPERTY, ipPrefix);
+        objs.put(SWITCH_PORT_ID_PROPERTY, switchPortId);
+
+        if (mplsLabel != null)
+            objs.put(MPLS_LABEL_PROPERTY, String.valueOf(mplsLabel));
+        if (nextHop != null)
+            objs.put(NEXT_HOP_PROPERTY, nextHop);
+
+        intentMappingService.add(siteName, objs);
+    }
+
+    /**
+     * @param siteName
+     *            Name of the member
+     * @return Map of parameters related to the member
+     */
+    public Map<String, String> get(String siteName) {
+        return intentMappingService.get(siteName);
+    }
+
+    /**
+     * @param siteName
+     *            Name of the member
+     * @return Return true if transaction succeed, otherwise false
+     */
+    public boolean delete(String siteName) {
+        try {
+            // TODO: Implement delete() in mapping service
+            // By now, it's going to overwrite data for this key
+            intentMappingService.add(siteName, null);
+            return true;
+        } catch (Exception e) {
+            LOG.error("Error deleting from NIC's mapping service {}", e);
+            throw e;
+        }
+    }
+}
diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MplsLabelManagerService.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/MplsLabelManagerService.java
new file mode 100644 (file)
index 0000000..f901995
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.Label;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MplsLabelManagerService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MplsLabelManagerService.class);
+    private static final Integer MAX_MPLS_LABEL = 524288;
+    private static InstanceIdentifier<Label> LABEL_IID = null;
+    public static final InstanceIdentifier<MplsLabels> MPLS_LABELS_IID = IidFactory.getMplsLabelsIid();
+    private final DataBroker dataBroker;
+    private final Random random = new Random();
+    private final MdsalUtils mdsal;
+
+    public MplsLabelManagerService(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+        this.mdsal = new MdsalUtils(this.dataBroker);
+    }
+
+    /**
+     * Generate a unique Mpls Label
+     * Mpls label is of length 20 bits maximum
+     * @return :next unique Mpls label value
+     */
+    public Long getUniqueLabel(Endpoint endpoint)  {
+        Long nextUniqueLabel = (long) random.nextInt(MAX_MPLS_LABEL);
+        while(checkIsLabelUsed(nextUniqueLabel)) {
+            nextUniqueLabel = (long) random.nextInt(MAX_MPLS_LABEL);
+        }
+        updateToLabelStore(nextUniqueLabel, endpoint, true);
+        return nextUniqueLabel;
+    }
+
+    /**
+     * Delete label from datastore
+     * @param endpoint :endpoint whose label needs to be deleted
+     */
+    public void deleteLabel(Endpoint endpoint)  {
+        Map<Long, String> labelMap = getAllLabels();
+        for (Map.Entry<Long, String> labelEntry : labelMap.entrySet()) {
+            if(labelEntry.getValue().equalsIgnoreCase(endpoint.getSiteName())) {
+                updateToLabelStore(labelEntry.getKey(), endpoint, false);
+            }
+        }
+    }
+
+    /**
+     * Update the model for Labels with used Mpls label values
+     * @param label :mpls label allocated to an endpoint
+     * @param endpoint :endpoint to which mpls label is allocated to
+     * @param add :true if add label to datastore, false to delete label from datastore
+     */
+    private void updateToLabelStore(Long label, Endpoint endpoint, boolean add) {
+        LABEL_IID = IidFactory.getLabelIid(label);
+        Label mplsLabel = new LabelBuilder().
+                setKey(new LabelKey(label)).
+                setLabelId(label).
+                setSiteName(endpoint.getSiteName()).
+                setIpPrefix(endpoint.getIpPrefix()).
+                setSwitchPortId(endpoint.getSwitchPortId()).build();
+
+        if(add) {
+            mdsal.put(LogicalDatastoreType.OPERATIONAL, LABEL_IID, mplsLabel);
+            LOG.info("Add mpls label to operational datastore: {} for endpoint: {}", label, endpoint.getSiteName());
+        } else {
+            mdsal.delete(LogicalDatastoreType.OPERATIONAL, LABEL_IID);
+            LOG.info("Delete mpls label from operational datastore: {} for endpoint: {}", label, endpoint.getSiteName());
+        }
+    }
+
+    /**
+     * Check if label is already allocated to any endpoint
+     * @param nextUniqueLabel :value of mpls label
+     * @return :true is label is already used else false
+     */
+    private boolean checkIsLabelUsed(Long nextUniqueLabel) {
+        Map<Long, String> labelMap = getAllLabels();
+        if(labelMap.containsKey(nextUniqueLabel)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Get a map of all the labels allocated to the endpoints
+     * @return :hashmap of labels as key, site names as value
+     */
+    private Map<Long, String> getAllLabels() {
+        Map<Long, String> labelMap = new HashMap<>();
+        MplsLabels mplsLabels = mdsal.read(LogicalDatastoreType.OPERATIONAL, MPLS_LABELS_IID);
+        if(mplsLabels != null) {
+            for (Label label : mplsLabels.getLabel()) {
+                labelMap.put(label.getLabelId(), label.getSiteName());
+            }
+        }
+        return labelMap;
+    }
+}
diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/VpnintentProvider.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/VpnintentProvider.java
new file mode 100644 (file)
index 0000000..1618bb1
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import java.util.concurrent.Future;
+
+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;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.nic.mapping.api.IntentMappingService;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.AddVpnEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.FailoverType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnintentService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntentsKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class VpnintentProvider implements VpnintentService, BindingAwareProvider, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VpnintentProvider.class);
+    public static final InstanceIdentifier<MplsLabels> LABELS_IID = IidFactory.getMplsLabelsIid();
+    public static final InstanceIdentifier<Vpns> VPN_IID = IidFactory.getVpnsIid();
+    public static final InstanceIdentifier<VpnIntents> VPN_INTENT_IID = IidFactory.getVpnIntentIid();
+    public static final InstanceIdentifier<Endpoint> ENDPOINT_IID = IidFactory.getEndpointIid();
+
+    private DataBroker dataBroker;
+    private IntentMappingService intentMappingService;
+    private BindingAwareBroker.RpcRegistration<VpnintentService> rpcRegistration = null;
+    private MdsalUtils mdsal;
+
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        LOG.info("VpnintentProvider Session Initiated");
+        dataBroker = session.getSALService(DataBroker.class);
+        rpcRegistration = session.addRpcImplementation(VpnintentService.class, this);
+        this.mdsal = new MdsalUtils(this.dataBroker);
+
+        // Load IntentMappingService Reference
+        loadIntentMappingServiceReference();
+
+        Vpns vpns = new VpnsBuilder().build();
+        MplsLabels labels = new MplsLabelsBuilder().build();
+
+        // Initialize MD-SAL data store for vpn-intents and mpls-labels
+        initDatastore(LogicalDatastoreType.CONFIGURATION, VPN_IID, vpns);
+        initDatastore(LogicalDatastoreType.OPERATIONAL, LABELS_IID, labels);
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("VpnintentProvider Closed");
+    }
+
+    private <T extends DataObject> void initDatastore(LogicalDatastoreType store, InstanceIdentifier<T> iid, T object) {
+        // Put data to MD-SAL data store
+        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+        transaction.put(store, iid, object);
+
+        // Perform the tx.submit asynchronously
+        Futures.addCallback(transaction.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(final Void result) {
+                LOG.info("initDatastore for VPN-Intents: transaction succeeded");
+            }
+
+            @Override
+            public void onFailure(final Throwable throwable) {
+                LOG.error("initDatastore for VPN-Intents: transaction failed");
+            }
+        });
+        LOG.info("initDatastore: data populated: {}, {}, {}", store, iid, object);
+    }
+
+    @Override
+    public Future<RpcResult<Void>> removeVpn(RemoveVpnInput input) {
+        InstanceIdentifier<VpnIntents> vpnIdentifier = InstanceIdentifier.builder(Vpns.class)
+                .child(VpnIntents.class, new VpnIntentsKey(input.getVpnName())).build();
+        MappingServiceManager msManager = new MappingServiceManager(intentMappingService);
+        MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+
+        VpnIntents vpn = getVpn(input.getVpnName());
+
+        if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) {
+            for (Endpoint endpoint : vpn.getEndpoint()) {
+                // Release MPLS label
+                mplsManager.deleteLabel(endpoint);
+
+                // Remove all intents related to this endpoint
+                IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+                intentManager.removeIntentsByEndpoint(endpoint.getSiteName());
+
+                // Remove info from Mapping Service
+                msManager.delete(endpoint.getSiteName());
+            }
+        }
+
+        mdsal.delete(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+        LOG.info("Deleted VPN {}", input.getVpnName());
+        return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+    }
+
+    @Override
+    public Future<RpcResult<Void>> addVpnEndpoint(AddVpnEndpointInput input) {
+        Endpoint currentEndpoint = new EndpointBuilder().setIpPrefix(input.getIpPrefix())
+                .setSiteName(input.getSiteName()).setSwitchPortId(input.getSwitchPortId())
+                .setKey(new EndpointKey(input.getSiteName())).build();
+        VpnIntents vpn = getVpn(input.getVpnName());
+        String failOverType = null;
+        if (vpn.isPathProtection() && vpn.getFailoverType()!= null) {
+            if (vpn.getFailoverType().equals(FailoverType.FastReroute)) {
+                failOverType = IntentServiceManager.FAST_REROUTE;
+            } else if(vpn.getFailoverType().equals(FailoverType.SlowReroute)) {
+                failOverType = IntentServiceManager.SLOW_REROUTE;
+            }
+        }
+
+        MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+
+        // Get unique MPLS label
+        Long mplsLabel = mplsManager.getUniqueLabel(currentEndpoint);
+
+        // Add info into Mapping Service
+        MappingServiceManager msManager = new MappingServiceManager(intentMappingService);
+        msManager.add(currentEndpoint.getSiteName(), extractIP(currentEndpoint.getIpPrefix()),
+                currentEndpoint.getSwitchPortId(), mplsLabel, null);
+
+        if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) {
+            IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+
+            for (Endpoint member : vpn.getEndpoint()) {
+                // Create mesh of Intents
+                intentManager.addIntent(member.getSiteName(), currentEndpoint.getSiteName(),
+                        IntentServiceManager.ACTION_ALLOW, failOverType);
+                intentManager.addIntent(currentEndpoint.getSiteName(), member.getSiteName(),
+                        IntentServiceManager.ACTION_ALLOW, failOverType);
+            }
+        }
+        // Associate endpoint with VPN
+        addEndpointToVpn(vpn, currentEndpoint);
+
+        return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+    }
+
+    /**
+     * @param IpPrefix
+     *            object
+     * @return String representation of IP prefix
+     */
+    private String extractIP(IpPrefix ipPrefix) {
+        String ip = null;
+        if (ipPrefix.getIpv4Prefix() != null) {
+            ip = ipPrefix.getIpv4Prefix().getValue();
+        } else if (ipPrefix.getIpv6Prefix() != null) {
+            ip = ipPrefix.getIpv6Prefix().getValue();
+        }
+        return ip;
+    }
+
+    /**
+     * @param vpnName
+     *            VPN name
+     * @return VPN instance
+     */
+    private VpnIntents getVpn(String vpnName) {
+        InstanceIdentifier<VpnIntents> identifier = InstanceIdentifier.builder(Vpns.class)
+                .child(VpnIntents.class, new VpnIntentsKey(vpnName)).build();
+
+        VpnIntents vpnIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, identifier);
+        Preconditions.checkNotNull(vpnIntents);
+        return vpnIntents;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> removeVpnEndpoint(RemoveVpnEndpointInput input) {
+        Endpoint endpoint = getEndpoint(input.getVpnName(), input.getSiteName());
+
+        // Release MPLS label
+        MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+        mplsManager.deleteLabel(endpoint);
+
+        // Remove all intents related to this endpoint
+        IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+        intentManager.removeIntentsByEndpoint(input.getSiteName());
+
+        // Remove endpoint from VPN
+        removeEndpointFromVpn(input.getVpnName(), input.getSiteName());
+
+        return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+    }
+
+    /**
+     * @param siteName
+     *            Site name of the VPN member
+     * @return VPN member (Endpoint)
+     */
+    private Endpoint getEndpoint(String vpnName, String siteName) {
+        InstanceIdentifier<Endpoint> endpointID = InstanceIdentifier.builder(Vpns.class)
+                .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName))
+                .build();
+
+        return mdsal.read(LogicalDatastoreType.CONFIGURATION, endpointID);
+    }
+
+    /**
+     * @param vpnName
+     *            VPN name
+     * @param siteName
+     *            Site name
+     */
+    private void removeEndpointFromVpn(String vpnName, String siteName) {
+        InstanceIdentifier<Endpoint> identifier = InstanceIdentifier.builder(Vpns.class)
+                .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName))
+                .build();
+
+        mdsal.delete(LogicalDatastoreType.CONFIGURATION, identifier);
+        LOG.info("Deleted VPN member : {} from VPN: {}", siteName, vpnName);
+    }
+
+    /**
+     * @param vpn
+     *            VPN
+     * @param vpnMember
+     *            VPN member (endpoint)
+     */
+    private void addEndpointToVpn(VpnIntents vpn, Endpoint vpnMember) {
+        InstanceIdentifier<Endpoint> identifier = InstanceIdentifier.builder(Vpns.class)
+                .child(VpnIntents.class, vpn.getKey())
+                .child(Endpoint.class, vpnMember.getKey()).build();
+
+        mdsal.put(LogicalDatastoreType.CONFIGURATION, identifier, vpnMember);
+        LOG.info("Added VPN member : {} to VPN: {}", vpnMember.getSiteName(), vpn.getVpnName());
+    }
+
+    /**
+     * Load IntentMappingService reference
+     */
+    private void loadIntentMappingServiceReference() {
+        ServiceReference<?> serviceReference = getBundleCtx().getServiceReference(IntentMappingService.class);
+        intentMappingService = (IntentMappingService) getBundleCtx().getService(serviceReference);
+    }
+
+    private BundleContext getBundleCtx() {
+        return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+    }
+}
diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/utils/IidFactory.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/utils/IidFactory.java
new file mode 100644 (file)
index 0000000..e08cf67
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.utils;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.Label;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IidFactory {
+
+    public static InstanceIdentifier<MplsLabels> getMplsLabelsIid() {
+        return InstanceIdentifier.builder(MplsLabels.class).build();
+    }
+
+    public static InstanceIdentifier<Label> getLabelIid(Long label) {
+        return InstanceIdentifier.create(MplsLabels.class).child(Label.class, new LabelKey(label));
+    }
+
+    public static InstanceIdentifier<Intents> getIntentsIid() {
+        return InstanceIdentifier.builder(Intents.class).build();
+    }
+
+    public static InstanceIdentifier<Vpns> getVpnsIid() {
+        return InstanceIdentifier.builder(Vpns.class).build();
+    }
+
+    public static InstanceIdentifier<VpnIntents> getVpnIntentIid() {
+        return InstanceIdentifier.builder(Vpns.class).child(VpnIntents.class).build();
+    }
+
+    public static InstanceIdentifier<Endpoint> getEndpointIid() {
+        return InstanceIdentifier.builder(Vpns.class).child(VpnIntents.class).child(Endpoint.class).build();
+    }
+}
diff --git a/vpnintent/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpnintent/impl/rev141210/VpnintentImplModule.java b/vpnintent/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpnintent/impl/rev141210/VpnintentImplModule.java
new file mode 100644 (file)
index 0000000..7d0cfb1
--- /dev/null
@@ -0,0 +1,26 @@
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210;
+
+import org.opendaylight.vpnservice.impl.VpnintentProvider;
+
+public class VpnintentImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210.AbstractVpnintentImplModule {
+    public VpnintentImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public VpnintentImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210.VpnintentImplModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        VpnintentProvider provider = new VpnintentProvider();
+        getBrokerDependency().registerProvider(provider);
+        return provider;
+    }
+
+}
diff --git a/vpnintent/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpnintent/impl/rev141210/VpnintentImplModuleFactory.java b/vpnintent/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpnintent/impl/rev141210/VpnintentImplModuleFactory.java
new file mode 100644 (file)
index 0000000..a369ccc
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: vpnintent-impl yang module local name: vpnintent-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Dec 16 22:44:32 EST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210;
+public class VpnintentImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210.AbstractVpnintentImplModuleFactory {
+
+}
diff --git a/vpnintent/impl/src/main/yang/vpnintent-impl.yang b/vpnintent/impl/src/main/yang/vpnintent-impl.yang
new file mode 100644 (file)
index 0000000..1016f7e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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 INTERNAL
+ */
+module vpnintent-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:vpnintent:impl";
+    prefix "vpnintent-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+    description
+        "Service definition for vpnintent project";
+
+    revision "2014-12-10" {
+        description
+            "Initial revision";
+    }
+
+    identity vpnintent-impl {
+        base config:module-type;
+        config:java-name-prefix VpnintentImpl;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case vpnintent-impl {
+            when "/config:modules/config:module/config:type = 'vpnintent-impl'";
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+            container rpc-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-rpc-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/IntentServiceManagerTest.java b/vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/IntentServiceManagerTest.java
new file mode 100644 (file)
index 0000000..71ef33c
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@PrepareForTest({IntentServiceManager.class})
+@RunWith(PowerMockRunner.class)
+public class IntentServiceManagerTest {
+
+    private static final String SRC_SITE_NAME = "site a";
+    private static final String DST_SITE_NAME = "site b";
+    private static final String INTENT_ALLOW_ACTION = "ALLOW";
+    private IntentServiceManager intentServiceManager;
+    @Mock private MdsalUtils mdsal;
+
+    @Before
+    public void setUp() throws Exception {
+        intentServiceManager = mock(IntentServiceManager.class, Mockito.CALLS_REAL_METHODS);
+        MemberModifier.field(IntentServiceManager.class, "mdsal").set(intentServiceManager, mdsal);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testAddIntent() throws Exception {
+        IntentBuilder intentBldr = mock(IntentBuilder.class);
+        PowerMockito.whenNew(IntentBuilder.class).withNoArguments().thenReturn(intentBldr);
+        when(intentBldr.setId(any(Uuid.class))).thenReturn(intentBldr);
+        when(intentBldr.setSubjects(any(List.class))).thenReturn(intentBldr);
+        when(intentBldr.setActions(any(List.class))).thenReturn(intentBldr);
+        when(intentBldr.setConstraints(any(List.class))).thenReturn(intentBldr);
+        when(intentBldr.build()).thenReturn(mock(Intent.class));
+
+        Intents currentIntents = mock(Intents.class);
+        PowerMockito.when(mdsal.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(currentIntents);
+        IntentsBuilder intentsBldr = mock(IntentsBuilder.class);
+        PowerMockito.whenNew(IntentsBuilder.class).withNoArguments().thenReturn(intentsBldr);
+        when(intentsBldr.setIntent(any(List.class))).thenReturn(intentsBldr);
+        PowerMockito.when(mdsal.put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Intents.class))).thenReturn(true);
+
+        intentServiceManager.addIntent(SRC_SITE_NAME, DST_SITE_NAME, INTENT_ALLOW_ACTION, "fast-reroute");
+        verify(intentBldr).setId(any(Uuid.class));
+        verify(mdsal).read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+        verify(mdsal).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Intents.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testRemoveIntents() {
+        Uuid id = mock(Uuid.class);
+        when(mdsal.delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(true);
+
+        intentServiceManager.removeIntent(id);
+        verify(mdsal).delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+    }
+}
diff --git a/vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/MappingServiceManagerTests.java b/vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/MappingServiceManagerTests.java
new file mode 100644 (file)
index 0000000..2fa5cb3
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.nic.mapping.api.IntentMappingService;
+
+public class MappingServiceManagerTests {
+
+    @Test
+    public void addInfo() {
+        // Arrange
+        String siteName = "UoR";
+        String ipPrefix = "16.101.233.2/8";
+        String switchPortId = "openflow:1:3";
+        long mplsLabel = 10L;
+        String nextHop = "16.101.233.1/8";
+
+        Map<String, String> map = new HashMap<>();
+        map.put("ip_prefix", ipPrefix);
+        map.put("switch_port", switchPortId);
+        map.put("mpls_label", String.valueOf(mplsLabel));
+        map.put("next_hop", nextHop);
+
+        IntentMappingService mapSvc = mock(IntentMappingService.class);
+        when(mapSvc.get(any(String.class))).thenReturn(map);
+
+        MappingServiceManager manager = new MappingServiceManager(mapSvc);
+
+        // Act
+        manager.add(siteName, ipPrefix, switchPortId, mplsLabel, nextHop);
+
+        Map<String, String> returnedObjs = manager.get(siteName);
+
+        // Assert
+        assertEquals(ipPrefix, returnedObjs.get("ip_prefix"));
+        assertEquals(switchPortId, returnedObjs.get("switch_port"));
+        assertEquals(mplsLabel, Long.parseLong(returnedObjs.get("mpls_label")));
+        assertEquals(nextHop, returnedObjs.get("next_hop"));
+    }
+
+    @Test
+    public void removeInfo() {
+        // Arrange
+        String siteName = "UoR";
+        String ipPrefix = "16.101.233.2/8";
+        String switchPortId = "openflow:1:3";
+
+        Map<String, String> map = new HashMap<>();
+        map.put("ip_prefix", ipPrefix);
+        map.put("switch_port", switchPortId);
+
+        IntentMappingService mapSvc = mock(IntentMappingService.class);
+
+        MappingServiceManager manager = new MappingServiceManager(mapSvc);
+
+        // Add first to delete next
+        manager.add(siteName, ipPrefix, switchPortId, null, null);
+
+        // Act
+        boolean result = manager.delete(siteName);
+
+        // Assert
+        assertTrue(result);
+    }
+}
diff --git a/vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/VpnintentProviderTest.java b/vpnintent/impl/src/test/java/org/opendaylight/vpnservice/impl/VpnintentProviderTest.java
new file mode 100644 (file)
index 0000000..a23d8ae
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import static org.mockito.Mockito.mock;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+
+public class VpnintentProviderTest {
+    @Ignore
+    @Test
+    public void testOnSessionInitiated() {
+        VpnintentProvider provider = new VpnintentProvider();
+
+        // ensure no exceptions
+        // currently this method is empty
+        provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
+    }
+
+    @Ignore
+    @Test
+    public void testClose() throws Exception {
+        VpnintentProvider provider = new VpnintentProvider();
+
+        // ensure no exceptions
+        // currently this method is empty
+        provider.close();
+    }
+}
diff --git a/vpnintent/pom.xml b/vpnintent/pom.xml
new file mode 100644 (file)
index 0000000..32d0504
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <parent>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <artifactId>odlparent-lite</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.opendaylight.vpnservice</groupId>
+  <artifactId>vpnintent-aggregator</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <name>vpnintent</name>
+  <packaging>pom</packaging>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <modules>
+    <module>api</module>
+    <module>impl</module>
+  </modules>
+  <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
+
diff --git a/vpnintent/resources/vpnintent.postman_collection b/vpnintent/resources/vpnintent.postman_collection
new file mode 100644 (file)
index 0000000..f1a5d92
--- /dev/null
@@ -0,0 +1,384 @@
+{
+       "id": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+       "name": "VPN Intents",
+       "description": "Apply protection and failover-type constraints to VpnService and NIC. When protections is set to true, and failover type is either soft-reroute or hard-reroute then the end-to-end connectivity is self-healing in case of link/node failure. VpnService shall create Intent object with constraints embedded in it (constraints are set by users) and NIC renders flows according based on the constraints.\n\nDisjoint Path Calculation using Suurballe Algorithm when soft-reroute constraint is applied to NIC, two disjoint paths are calculated. When one of the paths is non-usable due to a link/node failure the other disjoint path is automatically invoked to push required flows for all the intents that get affection by the failed path.\n\nDelete flows from the switch when an intent is removed: NIC did not support deleting flows from the nodes when an intent was removed, this was also fixed.",
+       "order": [],
+       "folders": [
+               {
+                       "id": "d424223b-11b7-b00d-3875-70b5fb4e6e85",
+                       "name": "Add Members to VPN",
+                       "description": "",
+                       "order": [
+                               "bfcc70b5-208a-d64e-7277-f4174b5f9ff9",
+                               "45328601-ed77-b7ff-0ae6-c5734c69c170",
+                               "84f7e114-532c-02d4-45fa-6e335f2a7e5d",
+                               "6421391f-20de-e31b-00a4-5cf36297c074"
+                       ],
+                       "owner": "255113",
+                       "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+               },
+               {
+                       "id": "2049f3c6-ebf5-a456-61de-ee9abd1811f4",
+                       "name": "Create VPN",
+                       "description": "",
+                       "order": [
+                               "e5f75d2a-c350-e601-5029-e6e5ea736eef",
+                               "91d91020-d5e0-2aaf-6c09-ed9cdec077de",
+                               "72ac6ee2-90a8-36b1-0dda-9eb886df197c"
+                       ],
+                       "owner": "255113",
+                       "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+               },
+               {
+                       "id": "a2deb454-a0e6-3870-0c64-ba7fdffaccba",
+                       "name": "MPLS Label Management",
+                       "description": "Includes a set of GET operations to access the labels assigned to each member",
+                       "order": [
+                               "e7ba99ee-7804-d411-e652-9d932687a35c"
+                       ],
+                       "owner": "255113",
+                       "collectionId": "efd3dae9-0818-468a-0d86-86fcec008d22"
+               },
+               {
+                       "id": "118a7d9f-7925-4e75-d59a-f9c151b1c4c4",
+                       "name": "Network Intent Composition Operations",
+                       "description": "GET operations to check the state of Intents",
+                       "order": [
+                               "109d1ae7-bdd4-907e-be5d-61b6f493640b"
+                       ],
+                       "owner": "255113",
+                       "collectionId": "748af960-874f-028d-cbd0-74134a3c6db7"
+               },
+               {
+                       "id": "3ab1d430-5cc5-f506-0619-b827cc6f645b",
+                       "name": "Remove Member from VPN",
+                       "description": "",
+                       "order": [
+                               "d3250d1d-ca8d-9a31-dec7-4ded8720e530",
+                               "42034ad0-1789-a773-6be3-9b9b5c4881bf",
+                               "13757df8-f5ea-c933-a991-b9a8e4d60b07",
+                               "0063438d-94b1-5ca3-88f2-1d789f3d2251"
+                       ],
+                       "owner": "255113",
+                       "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+               },
+               {
+                       "id": "3958cf6c-b82e-f0d4-a5c3-ce0bb85464c7",
+                       "name": "Remove VPN",
+                       "description": "",
+                       "order": [
+                               "63050e81-9cac-5de5-2180-7ed5c6bd361a",
+                               "b0ac20bf-7cad-e958-761c-a83a456afdd4"
+                       ],
+                       "owner": "255113"
+               }
+       ],
+       "timestamp": 1450878947771,
+       "owner": "255113",
+       "remoteLink": "",
+       "public": false,
+       "requests": [
+               {
+                       "id": "0063438d-94b1-5ca3-88f2-1d789f3d2251",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741595237,
+                       "name": "Remove Member 4 (site 4)  from unprotected VPN",
+                       "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN unprotected\",\n        \"site-name\": \"site 4\"\n   }\n}"
+               },
+               {
+                       "id": "109d1ae7-bdd4-907e-be5d-61b6f493640b",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/config/intent:intents/",
+                       "pathVariables": {},
+                       "preRequestScript": "",
+                       "method": "GET",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "data": [],
+                       "dataMode": "params",
+                       "name": "GET intents",
+                       "description": "Gets a list of intents added",
+                       "descriptionFormat": "html",
+                       "time": 1450721033712,
+                       "version": 2,
+                       "responses": [],
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "folder": "118a7d9f-7925-4e75-d59a-f9c151b1c4c4"
+               },
+               {
+                       "id": "13757df8-f5ea-c933-a991-b9a8e4d60b07",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741569695,
+                       "name": "Remove Member 3 (site 3)   from unprotected VPN",
+                       "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN unprotected\",\n        \"site-name\": \"site 3\"\n   }\n}"
+               },
+               {
+                       "id": "42034ad0-1789-a773-6be3-9b9b5c4881bf",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741544712,
+                       "name": "Remove Member 2 (site 2)   from protected VPN",
+                       "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN protected\",\n        \"site-name\": \"site 2\"\n   }\n}"
+               },
+               {
+                       "id": "45328601-ed77-b7ff-0ae6-c5734c69c170",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741386479,
+                       "name": "Add Member 2 (site 2)  to protected VPN",
+                       "description": "Add a Member to a protected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN protected\",\n        \"site-name\": \"site 2\",\n        \"ip-prefix\": \"10.0.0.2/32\",\n        \"switch-port-id\": \"openflow:2:1\"\n   }\n}"
+               },
+               {
+                       "id": "63050e81-9cac-5de5-2180-7ed5c6bd361a",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741509183,
+                       "name": "Remove protected VPN",
+                       "description": "Delete a VPN\n\nParameters description\nvpn-name: The VPN that needs to be deleted",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN protected\"\n   }\n}"
+               },
+               {
+                       "id": "6421391f-20de-e31b-00a4-5cf36297c074",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741358417,
+                       "name": "Add Member 4 (site 4)  to unprotected VPN",
+                       "description": "Add a Member to an unprotected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN unprotected\",\n        \"site-name\": \"site 4\",\n        \"ip-prefix\": \"10.0.0.4/32\",\n        \"switch-port-id\": \"openflow:4:1\"\n   }\n}"
+               },
+               {
+                       "id": "72ac6ee2-90a8-36b1-0dda-9eb886df197c",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+                       "pathVariables": {},
+                       "preRequestScript": "",
+                       "method": "GET",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "data": [],
+                       "dataMode": "params",
+                       "name": "GET VPNs",
+                       "description": "Gets a list of all the VPNs along with the list of members that belong to these VPNs",
+                       "descriptionFormat": "html",
+                       "time": 1450716801343,
+                       "version": 2,
+                       "responses": [],
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "folder": "2049f3c6-ebf5-a456-61de-ee9abd1811f4"
+               },
+               {
+                       "id": "84f7e114-532c-02d4-45fa-6e335f2a7e5d",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741323406,
+                       "name": "Add Member 3 (site 3)  to unprotected VPN",
+                       "description": "Add a Member to an unprotected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN unprotected\",\n        \"site-name\": \"site 3\",\n        \"ip-prefix\": \"10.0.0.1/32\",\n        \"switch-port-id\": \"openflow:3:1\"\n   }\n}"
+               },
+               {
+                       "id": "91d91020-d5e0-2aaf-6c09-ed9cdec077de",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741250149,
+                       "name": "Create an unprotected VPN",
+                       "description": "Create a protected VPN by pushing to config data tree to the Vpn-intents Yang model\n\nParameters description\nvpn-name: The name of the VPN that you intend to create\nprotection: True if path protection is needed\nfailover-type: Type of failover mechanism\n               - slow-reroute\n               - fast-reroute",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n    \"vpn-intents\": [\n        {\n            \"vpn-name\": \"VPN unprotected\",\n            \"path-protection\": \"false\",\n            \"failover-type\": \"slow-reroute\"\n        }\n    ]\n}"
+               },
+               {
+                       "id": "b0ac20bf-7cad-e958-761c-a83a456afdd4",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741501187,
+                       "name": "Remove unprotected VPN",
+                       "description": "Delete a VPN\n\nParameters description\nvpn-name: The VPN that needs to be deleted",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN unprotected\"\n   }\n}"
+               },
+               {
+                       "id": "bfcc70b5-208a-d64e-7277-f4174b5f9ff9",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741369995,
+                       "name": "Add Member 1 (site 1)  to protected VPN",
+                       "description": "Add a Member to a protected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN protected\",\n        \"site-name\": \"site 1\",\n        \"ip-prefix\": \"10.0.0.1/32\",\n        \"switch-port-id\": \"openflow:1:1\"\n   }\n}"
+               },
+               {
+                       "id": "d3250d1d-ca8d-9a31-dec7-4ded8720e530",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741522615,
+                       "name": "Remove Member 1 (site 1)  from protected VPN",
+                       "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n \"input\": {\n       \"vpn-name\": \"VPN protected\",\n        \"site-name\": \"site 1\"\n   }\n}"
+               },
+               {
+                       "id": "e5f75d2a-c350-e601-5029-e6e5ea736eef",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "POST",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452741238916,
+                       "name": "Create a protected VPN",
+                       "description": "Create a protected VPN by pushing to config data tree to the Vpn-intents Yang model\n\nParameters description\nvpn-name: The name of the VPN that you intend to create\nprotection: True if path protection is needed\nfailover-type: Type of failover mechanism\n               - slow-reroute\n               - fast-reroute",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "rawModeData": "{\n    \"vpn-intents\": [\n        {\n            \"vpn-name\": \"VPN protected\",\n            \"path-protection\": \"true\",\n            \"failover-type\": \"slow-reroute\"\n        }\n    ]\n}"
+               },
+               {
+                       "id": "e7ba99ee-7804-d411-e652-9d932687a35c",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/operational/vpnintent:mpls-labels",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1452282516268,
+                       "name": "GET all unique MPLS Labels",
+                       "description": "Gets a list of unique labels assigned to every Member in the VPN",
+                       "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+                       "responses": [],
+                       "folder": "a2deb454-a0e6-3870-0c64-ba7fdffaccba"
+               }
+       ]
+}
\ No newline at end of file
index f097eaeea7e23290b2f7aa2afaf467893a438e8c..4beb21ec9eb1b94d90bf637942dfae750f50c8d0 100644 (file)
@@ -49,6 +49,27 @@ module odl-l3vpn {
         }
     }
 
+    container vpn-to-extraroute {
+        config false;
+        list vpn {
+           key vrf-id;
+           leaf vrf-id {
+              description
+                 "The vrf-id command configures a route distinguisher (RD)
+                  for the IPv4 or IPv6 address family of a VPN instance or
+                  vpn instance name for internal vpn case.";
+              type string;
+           }
+           list extraroute {
+              key prefix;
+              leaf prefix {type string;}
+                     leaf nexthop-ip {
+                         type string;
+                     }
+           }
+        }
+    }
+
     /* Data models to adhere to restart requirements */
     container vpn-instance-to-vpn-id {
        list vpn-instance {
@@ -82,6 +103,7 @@ module odl-l3vpn {
               type string;
            }
 
+           leaf vpn-interface-count { type uint32; }
            uses vpn-route-list;
            list vpn-to-dpn-list {
                key dpnId;
index 599f70380f12b18ab36c76ea206378bed0b5ed61..206f884a3c6dcfb56bbd25669cd6e9c9bb33d7f2 100644 (file)
@@ -76,14 +76,14 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
         LOG.info("Received port UP event for interface {} ", interfaceName);
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
             configInterface = InterfaceUtils.getInterface(broker, interfaceName);
+        BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
         if (configInterface != null && configInterface.getType().equals(Tunnel.class)) {
-          BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
           if(intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
             //advertise all prefixes in all vpns for this dpn to bgp
             vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.ADVERTISE_ROUTE);
           }
         } else {
-          vpnInterfaceManager.processVpnInterfaceUp(interfaceName, intrf.getIfIndex());
+          vpnInterfaceManager.processVpnInterfaceUp(dpnId, interfaceName, intrf.getIfIndex());
         }
       } catch (Exception e) {
         LOG.error("Exception caught in Interface Operational State Up event", e);
@@ -103,20 +103,15 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
         LOG.info("Received port DOWN event for interface {} ", interfaceName);
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
             intf = InterfaceUtils.getInterface(broker, interfaceName);
+        BigInteger dpId = InterfaceUtils.getDpIdFromInterface(intrf);
         if (intf != null && intf.getType().equals(Tunnel.class)) {
-          // Get the dpId from del reference itself. Because interfaceManager.getDpnForInterface returns
-          // NPE because entry is already deleted in operational data store
-          BigInteger dpId = getDpIdFromInterface(intrf);
-          if (dpId == null) {
-            return;
-          }
           if(intrf.getOperStatus().equals(Interface.OperStatus.Down)) {
             //withdraw all prefixes in all vpns for this dpn from bgp
             vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
           }
         } else {
           if (VpnUtil.isVpnInterfaceConfigured(broker, interfaceName)) {
-            vpnInterfaceManager.processVpnInterfaceDown(interfaceName, intrf.getIfIndex(), true);
+            vpnInterfaceManager.processVpnInterfaceDown(dpId, interfaceName, intrf.getIfIndex(), true);
           }
         }
       } catch (Exception e) {
@@ -132,7 +127,7 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
       org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
           intf = InterfaceUtils.getInterface(broker, interfaceName);
       if (intf != null && intf.getType().equals(Tunnel.class)) {
-        BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
+        BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
         if(update.getOperStatus().equals(Interface.OperStatus.Up)) {
           //advertise all prefixes in all vpns for this dpn to bgp
           vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.ADVERTISE_ROUTE);
@@ -144,12 +139,4 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
 
     }
 
-  public BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface infState) {
-    org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
-        InterfaceUtils.getInterfaceStateFromOperDS(broker, infState.getName());
-    String lowerLayerIf = ifState.getLowerLayerIf().get(0);
-    NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
-    return new BigInteger(InterfaceUtils.getDpnFromNodeConnectorId(nodeConnectorId));
-  }
-
 }
index 75b076395e4895c9ecd99419cd61879bfd62f727..862a6c49c24a83f3d301f445ce0e7ad246b43f16 100644 (file)
@@ -21,4 +21,5 @@ public class VpnConstants {
     public static final BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
     public static final BigInteger COOKIE_L3_BASE = new BigInteger("8000000", 16);
     public static final String FLOWID_PREFIX = "L3.";
+    public static final long WAIT_TIME_IN_MILLISECONDS = 5000;
 }
index 525d30bd0cd1d3e970c139ffbefa99062218e71d..d4dd28813275770c4469305e425fc7ca74e2377a 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.vpnservice.mdsalutil.*;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
@@ -41,7 +42,7 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ArrayList;
-import java.util.concurrent.Future;
+import java.util.concurrent.*;
 
 import com.google.common.base.Optional;
 
@@ -73,7 +74,9 @@ import org.slf4j.LoggerFactory;
 
 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
+    private ListenerRegistration<DataChangeListener> listenerRegistration, opListenerRegistration;
+    private ConcurrentMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
+    private ExecutorService executorService = Executors.newSingleThreadExecutor();
     private final DataBroker broker;
     private final IBgpManager bgpManager;
     private IFibManager fibManager;
@@ -83,6 +86,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     private IdManagerService idManager;
     private OdlArputilService arpManager;
     private InterfaceStateChangeListener interfaceListener;
+    private VpnInterfaceOpListener vpnInterfaceOpListener;
     private ArpNotificationHandler arpNotificationHandler;
     protected enum UpdateRouteAction {
         ADVERTISE_ROUTE, WITHDRAW_ROUTE
@@ -98,6 +102,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         broker = db;
         this.bgpManager = bgpManager;
         interfaceListener = new InterfaceStateChangeListener(db, this);
+        vpnInterfaceOpListener = new VpnInterfaceOpListener();
         arpNotificationHandler = new ArpNotificationHandler(this, broker);
         notificationService.registerNotificationListener(arpNotificationHandler);
         registerListener(db);
@@ -133,10 +138,12 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         if (listenerRegistration != null) {
             try {
                 listenerRegistration.close();
+                opListenerRegistration.close();
             } catch (final Exception e) {
                 LOG.error("Error when cleaning up DataChangeListener.", e);
             }
             listenerRegistration = null;
+            opListenerRegistration = null;
         }
         LOG.info("VPN Interface Manager Closed");
     }
@@ -145,6 +152,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         try {
             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
                     getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
+            opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                                                                   getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
         } catch (final Exception e) {
             LOG.error("VPN Service DataChange listener registration fail!", e);
             throw new IllegalStateException("VPN Service registration Listener failed.", e);
@@ -159,13 +168,13 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     @Override
     protected void add(final InstanceIdentifier<VpnInterface> identifier,
             final VpnInterface vpnInterface) {
-        LOG.trace("key: {} , value: {}", identifier, vpnInterface );
+        LOG.trace("VPN Interface key: {} , value: {}", identifier, vpnInterface );
         addInterface(identifier, vpnInterface);
     }
 
     private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
                               final VpnInterface vpnInterface) {
-        LOG.trace("Add event - key: {}, value: {}" ,identifier, vpnInterface );
+        LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
         String interfaceName = key.getName();
 
@@ -173,11 +182,13 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
         if (interfaceState != null) {
             // Interface state is up
-            processVpnInterfaceUp(interfaceName, interfaceState.getIfIndex());
+            processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex());
+        } else {
+            LOG.trace("VPN interfaces are not yet operational.");
         }
     }
 
-    protected synchronized void processVpnInterfaceUp(String interfaceName, int lPortTag) {
+    protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag) {
 
         VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
         if(vpnInterface == null) {
@@ -186,9 +197,21 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
         String vpnName = vpnInterface.getVpnInstanceName();
         LOG.info("Binding vpn service to interface {} ", interfaceName);
-        bindService(vpnName, interfaceName, lPortTag);
-        updateDpnDbs(vpnName, interfaceName, true);
-        processVpnInterfaceAdjacencies(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+        long vpnId = VpnUtil.getVpnId(broker, vpnName);
+        if (vpnId == VpnConstants.INVALID_ID) {
+            LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
+            return;
+        }
+        if (VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName()) != null) {
+            LOG.trace("VPN Interface already provisioned , bailing out from here.");
+            return;
+        }
+        synchronized (interfaceName.intern()) {
+
+            bindService(dpId, vpnName, interfaceName, lPortTag);
+            updateDpnDbs(vpnName, interfaceName, true);
+            processVpnInterfaceAdjacencies(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+        }
 
     }
 
@@ -204,7 +227,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     }
 
-    private void bindService(String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+    private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
         int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
 
@@ -221,7 +244,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                                             VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
         VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
                           InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
-        makeArpFlow(VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName, vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
+        makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+                    vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
 
     }
 
@@ -284,7 +308,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
     }
 
-    private void makeArpFlow(short sIndex, int lPortTag, String vpnInterfaceName, long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
+    private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
+                             long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
         List<MatchInfo> matches = new ArrayList<MatchInfo>();
         BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
         BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
@@ -304,7 +329,6 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
 
         // Install the flow entry in L3_INTERFACE_TABLE
-        BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, vpnInterfaceName);
         String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
                     NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
         FlowEntity flowEntity;
@@ -350,7 +374,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         } else {
             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
                                     VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-                                    VpnUtil.getVpnInstanceOpData(rd, vpnId));
+                                    VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId));
             VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
             List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
                 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces =  new ArrayList<>();
@@ -423,13 +447,13 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
 
         if (existingVpnInterface.isPresent() && interfaceState != null) {
-            processVpnInterfaceDown(interfaceName, interfaceState.getIfIndex(), false);
+            processVpnInterfaceDown(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex(), false);
         } else {
             LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
         }
     }
 
-    protected synchronized void processVpnInterfaceDown(String interfaceName, int lPortTag, boolean isInterfaceStateDown) {
+    protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown) {
         VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
         if(vpnInterface == null) {
             LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
@@ -438,11 +462,24 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         String vpnName = vpnInterface.getVpnInstanceName();
         InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
 
-        removeAdjacenciesFromVpn(identifier, vpnInterface);
-        LOG.info("Unbinding vpn service from interface {} ", interfaceName);
-        unbindService(vpnName, interfaceName, lPortTag, isInterfaceStateDown);
-        updateDpnDbs(vpnName, interfaceName, false);
-        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, identifier, VpnUtil.DEFAULT_CALLBACK);
+        synchronized (interfaceName.intern()) {
+            removeAdjacenciesFromVpn(identifier, vpnInterface);
+            LOG.info("Unbinding vpn service from interface {} ", interfaceName);
+            unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown);
+
+            //wait till DCN for removal of vpn interface in operational DS arrives
+            Runnable notifyTask = new VpnNotifyTask();
+            synchronized (interfaceName.intern()) {
+                vpnIntfMap.put(interfaceName, notifyTask);
+                synchronized (notifyTask) {
+                    try {
+                        notifyTask.wait(VpnConstants.WAIT_TIME_IN_MILLISECONDS);
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+
+        }
     }
 
     private void removeAdjacenciesFromVpn(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
@@ -459,11 +496,11 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 for (Adjacency nextHop : nextHops) {
                     VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
                                       VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
-                    VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+                    /*VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
                                    VpnUtil.getPrefixToInterfaceIdentifier(
                                        VpnUtil.getVpnId(broker, intf.getVpnInstanceName()),
                                        nextHop.getIpAddress()),
-                                   VpnUtil.DEFAULT_CALLBACK);
+                                   VpnUtil.DEFAULT_CALLBACK);*/
                     if (rd.equals(intf.getVpnInstanceName())) {
                         //this is an internal vpn - the rd is assigned to the vpn instance name;
                         //remove from FIB directly
@@ -477,7 +514,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
 
-    private void unbindService(String vpnInstanceName, String vpnInterfaceName, int lPortTag, boolean isInterfaceStateDown) {
+    private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
+                               int lPortTag, boolean isInterfaceStateDown) {
         if (!isInterfaceStateDown) {
             VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION,
                            InterfaceUtils.buildServiceId(vpnInterfaceName,
@@ -485,7 +523,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                            VpnUtil.DEFAULT_CALLBACK);
         }
         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
-        makeArpFlow(VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+        makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
                     vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
     }
 
@@ -622,7 +660,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
                     setVrfEntry(vrfEntryList).build();
 
-        VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vrfTableId, vrfTableNew);
+        VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
     }
 
     public synchronized void removeFibEntryFromDS(String rd, String prefix) {
@@ -632,7 +670,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         InstanceIdentifierBuilder<VrfEntry> idBuilder =
             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
         InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
-        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, vrfEntryId, VpnUtil.DEFAULT_CALLBACK);
+        VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, VpnUtil.DEFAULT_CALLBACK);
 
     }
 
@@ -643,7 +681,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
 
-        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
+        VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
 
     }
 
@@ -676,7 +714,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug);
 
             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
-            addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label);
+            addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label, currVpnIntf.getName());
 
         }
 
@@ -720,7 +758,25 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     }
 
-    protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label) {
+    protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label, String intfName) {
+
+        //add extra route to vpn mapping; advertise with nexthop as tunnel ip
+        VpnUtil.syncUpdate(
+            broker,
+            LogicalDatastoreType.OPERATIONAL,
+            VpnUtil.getVpnToExtrarouteIdentifier(
+                (rd != null) ? rd : routerID, destination),
+            VpnUtil.getVpnToExtraroute(destination, nextHop));
+
+        if(intfName != null && !intfName.isEmpty()) {
+            BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName);
+            String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
+            if (nextHopIp == null && !nextHopIp.isEmpty()) {
+                LOG.error("NextHop for interface {} is null. Failed adding extra route for prefix {}", intfName, destination);
+                return;
+            }
+            nextHop = nextHopIp;
+        }
         if (rd != null) {
             addPrefixToBGP(rd, destination, nextHop, label);
         } else {
@@ -738,6 +794,73 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
     }
 
+    class VpnInterfaceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<VpnInterface> {
+
+        public VpnInterfaceOpListener() {
+            super(VpnInterface.class);
+        }
+
+        @Override
+        protected void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {
+            final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+            String interfaceName = key.getName();
+
+            //increment the vpn interface count in Vpn Instance Op Data
+            Long ifCnt = 0L;
+            String rd = getRouteDistinguisher(del.getVpnInstanceName());
+            if(rd.isEmpty()) rd = del.getVpnInstanceName();
+            VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
+            if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
+                ifCnt = vpnInstOp.getVpnInterfaceCount();
+            }
+
+            LOG.trace("VpnInterfaceOpListener remove: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
+
+            VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+                    VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                    VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
+
+            //TODO: Clean up the DPN List in Vpn Instance Op if ifCnt is zero
+
+            notifyTaskIfRequired(interfaceName);
+        }
+
+        private void notifyTaskIfRequired(String intfName) {
+            Runnable notifyTask = vpnIntfMap.remove(intfName);
+            if (notifyTask == null) {
+                return;
+            }
+            executorService.execute(notifyTask);
+        }
+
+        @Override
+        protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
+        }
+
+        @Override
+        protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
+            final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+            String interfaceName = key.getName();
+
+            //increment the vpn interface count in Vpn Instance Op Data
+            Long ifCnt = 0L;
+            String rd = getRouteDistinguisher(add.getVpnInstanceName());
+            if(rd.isEmpty()) rd = add.getVpnInstanceName();
+            VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
+            if(vpnInstOp != null &&  vpnInstOp.getVpnInterfaceCount() != null) {
+                ifCnt = vpnInstOp.getVpnInterfaceCount();
+            }
+
+            LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
+
+            VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+                    VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                    VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
+
+
+        }
+    }
+
     protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) {
 
         InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
index 5567d3e6206a47e3c47d2a65f283ff2ddc62ed3d..1a454018d0a3f912570d99da250693f6f9a03c19 100644 (file)
@@ -10,12 +10,15 @@ package org.opendaylight.vpnservice;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.*;
 
+import com.google.common.util.concurrent.CheckedFuture;
 import org.opendaylight.bgpmanager.api.IBgpManager;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 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.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnIdBuilder;
@@ -51,12 +54,15 @@ import com.google.common.util.concurrent.Futures;
 
 public class VpnManager extends AbstractDataChangeListener<VpnInstance> implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(VpnManager.class);
-    private ListenerRegistration<DataChangeListener> listenerRegistration, fibListenerRegistration;
+    private ListenerRegistration<DataChangeListener> listenerRegistration, fibListenerRegistration, opListenerRegistration;
+    private ConcurrentMap<String, Runnable> vpnOpMap = new ConcurrentHashMap<String, Runnable>();
+    private ExecutorService executorService = Executors.newSingleThreadExecutor();
     private final DataBroker broker;
     private final IBgpManager bgpManager;
     private IdManagerService idManager;
     private VpnInterfaceManager vpnInterfaceManager;
     private final FibEntriesListener fibListener;
+    private final VpnInstanceOpListener vpnInstOpListener;
 
     private static final FutureCallback<Void> DEFAULT_CALLBACK =
             new FutureCallback<Void>() {
@@ -80,6 +86,7 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
         broker = db;
         this.bgpManager = bgpManager;
         this.fibListener = new FibEntriesListener();
+        this.vpnInstOpListener = new VpnInstanceOpListener();
         registerListener(db);
     }
 
@@ -89,6 +96,9 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
                     getWildCardPath(), VpnManager.this, DataChangeScope.SUBTREE);
             fibListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
                     getFibEntryListenerPath(), fibListener, DataChangeScope.BASE);
+            opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                    getVpnInstanceOpListenerPath(), vpnInstOpListener, DataChangeScope.SUBTREE);
+
         } catch (final Exception e) {
             LOG.error("VPN Service DataChange listener registration fail !", e);
             throw new IllegalStateException("VPN Service registration Listener failed.", e);
@@ -103,6 +113,21 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
         this.vpnInterfaceManager = vpnInterfaceManager;
     }
 
+    private void waitForOpDataRemoval(String id) {
+        //wait till DCN for removal of all DPNs in VPN arrivaes
+        Runnable notifyTask = new VpnNotifyTask();
+        synchronized (id.intern()) {
+            vpnOpMap.put(id, notifyTask);
+            synchronized (notifyTask) {
+                try {
+                    notifyTask.wait(VpnConstants.WAIT_TIME_IN_MILLISECONDS);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+    }
+
     @Override
     protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
         LOG.trace("Remove VPN event - Key: {}, value: {}", identifier, del);
@@ -131,13 +156,15 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
 
         if (rd !=null) {
 
-            delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd));
             try {
                 bgpManager.deleteVrf(rd);
-            } catch(Exception e) {
+            } catch (Exception e) {
                 LOG.error("Exception when removing VRF from BGP", e);
             }
+            waitForOpDataRemoval(rd);
+            delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd));
         } else {
+            waitForOpDataRemoval(vpnName);
             delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
         }
     }
@@ -151,30 +178,30 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
     @Override
     protected void add(InstanceIdentifier<VpnInstance> identifier,
             VpnInstance value) {
-        LOG.trace("key: {}, value: {}", identifier, value);
+        LOG.trace("VPN Instance key: {}, value: {}", identifier, value);
         VpnAfConfig config = value.getIpv4Family();
         String rd = config.getRouteDistinguisher();
 
         long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, value.getVpnInstanceName());
-
+        LOG.trace("VPN instance to ID generated.");
         org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
             vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(value.getVpnInstanceName(), vpnId,
                                                                     (rd != null) ? rd : value.getVpnInstanceName());
 
-        asyncWrite(LogicalDatastoreType.CONFIGURATION,
+        syncWrite(LogicalDatastoreType.CONFIGURATION,
                    VpnUtil.getVpnInstanceToVpnIdIdentifier(value.getVpnInstanceName()),
                    vpnInstanceToVpnId, DEFAULT_CALLBACK);
 
 
         if(rd == null) {
-            asyncWrite(LogicalDatastoreType.OPERATIONAL,
+            syncWrite(LogicalDatastoreType.OPERATIONAL,
                     VpnUtil.getVpnInstanceOpDataIdentifier(value.getVpnInstanceName()),
-                    VpnUtil.getVpnInstanceOpData(value.getVpnInstanceName(), vpnId), DEFAULT_CALLBACK);
+                    VpnUtil.getVpnInstanceOpDataBuilder(value.getVpnInstanceName(), vpnId), DEFAULT_CALLBACK);
 
         } else {
-            asyncWrite(LogicalDatastoreType.OPERATIONAL,
+            syncWrite(LogicalDatastoreType.OPERATIONAL,
                        VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-                       VpnUtil.getVpnInstanceOpData(rd, vpnId), DEFAULT_CALLBACK);
+                       VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId), DEFAULT_CALLBACK);
 
             List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
 
@@ -200,6 +227,22 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
                 LOG.error("Exception when adding VRF to BGP", e);
             }
         }
+        //Try to add up vpn Interfaces if already in Operational Datastore
+        LOG.trace("Trying to add the vpn interfaces  -1.");
+        InstanceIdentifier<VpnInterfaces> vpnInterfacesId = InstanceIdentifier.builder(VpnInterfaces.class).build();
+        Optional<VpnInterfaces> optionalVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, vpnInterfacesId);
+
+        if(optionalVpnInterfaces.isPresent()) {
+            List<VpnInterface> vpnInterfaces = optionalVpnInterfaces.get().getVpnInterface();
+            for(VpnInterface vpnInterface : vpnInterfaces) {
+                if(vpnInterface.getVpnInstanceName().equals(value.getVpnInstanceName())) {
+                    LOG.debug("VpnInterface {} will be added from VPN {}", vpnInterface.getName(), value.getVpnInstanceName());
+                    vpnInterfaceManager.add(
+                                VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+
+                }
+            }
+        }
     }
 
     private InstanceIdentifier<?> getWildCardPath() {
@@ -211,6 +254,11 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
                 .child(VrfEntry.class);
     }
 
+    private InstanceIdentifier<?> getVpnInstanceOpListenerPath() {
+        return InstanceIdentifier.create(VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class);
+
+    }
+
     @Override
     public void close() throws Exception {
         if (listenerRegistration != null) {
@@ -229,6 +277,15 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
             }
             fibListenerRegistration = null;
         }
+        if (opListenerRegistration != null) {
+            try {
+                opListenerRegistration.close();
+            } catch (final Exception e) {
+                LOG.error("Error when cleaning up VPN Instance Operational entries DataChangeListener.", e);
+            }
+            opListenerRegistration = null;
+        }
+
         LOG.trace("VPN Manager Closed");
     }
 
@@ -254,6 +311,19 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
         Futures.addCallback(tx.submit(), callback);
     }
 
+    private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
+                                                   InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.put(datastoreType, path, data, true);
+        CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+        try {
+            futures.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error writing VPN instance to ID info to datastore (path, data) : ({}, {})", path, data);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
     protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
         InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(LogicalDatastoreType.OPERATIONAL, id);
@@ -327,4 +397,42 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
             }
         }
     }
+
+    class VpnInstanceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<VpnInstanceOpDataEntry> {
+
+        public VpnInstanceOpListener() {
+            super(VpnInstanceOpDataEntry.class);
+        }
+
+        @Override
+        protected void remove(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry del) {
+
+        }
+
+        @Override
+        protected void update(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry original, VpnInstanceOpDataEntry update) {
+            final VpnInstanceOpDataEntryKey key = identifier.firstKeyOf(VpnInstanceOpDataEntry.class, VpnInstanceOpDataEntryKey.class);
+            String vpnName = key.getVrfId();
+
+            LOG.trace("VpnInstanceOpListener update: vpn name {} interface count in Old VpnOp Instance {} in New VpnOp Instance {}" ,
+                            vpnName, original.getVpnInterfaceCount(), update.getVpnInterfaceCount() );
+
+            //if((original.getVpnToDpnList().size() != update.getVpnToDpnList().size()) && (update.getVpnToDpnList().size() == 0)) {
+            if((original.getVpnInterfaceCount() != update.getVpnInterfaceCount()) && (update.getVpnInterfaceCount() == 0)) {
+                notifyTaskIfRequired(vpnName);
+            }
+        }
+
+        private void notifyTaskIfRequired(String vpnName) {
+            Runnable notifyTask = vpnOpMap.remove(vpnName);
+            if (notifyTask == null) {
+                return;
+            }
+            executorService.execute(notifyTask);
+        }
+
+        @Override
+        protected void add(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry add) {
+        }
+    }
 }
diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnNotifyTask.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnNotifyTask.java
new file mode 100644 (file)
index 0000000..0611e34
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 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.vpnservice;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class VpnNotifyTask implements Runnable{
+    private static final Logger logger = LoggerFactory.getLogger(VpnNotifyTask.class);
+
+    @Override
+    public void run() {
+        logger.debug("Notify Task is running for the task {}", this);
+        synchronized (this) {
+            notifyAll();
+        }
+    }
+
+}
index 29ad638fa14ff79a3f8be1611ab740516db6ae54..10d69f961627900d630cd67991a9532e2e4c2914 100644 (file)
@@ -34,9 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 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.l3vpn.rev130911.PrefixToInterface;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
@@ -50,6 +48,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instanc
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
@@ -97,6 +100,16 @@ public class VpnUtil {
             vpnInterfaceName).setIpAddress(ipPrefix).build();
     }
 
+    static InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
+        return InstanceIdentifier.builder(VpnToExtraroute.class)
+                .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
+                 new ExtrarouteKey(ipPrefix)).build();
+    }
+
+    static Extraroute getVpnToExtraroute(String ipPrefix, String nextHop) {
+        return new ExtrarouteBuilder().setPrefix(ipPrefix).setNexthopIp(nextHop).build();
+    }
+
     static Adjacencies
     getVpnInterfaceAugmentation(List<Adjacency> nextHops) {
         return new AdjacenciesBuilder().setAdjacency(nextHops).build();
@@ -219,10 +232,23 @@ public class VpnUtil {
             .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
     }
 
-    static VpnInstanceOpDataEntry getVpnInstanceOpData(String rd, long vpnId) {
+    static VpnInstanceOpDataEntry getVpnInstanceOpDataBuilder(String rd, long vpnId) {
         return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).build();
     }
 
+    static VpnInstanceOpDataEntry updateIntfCntInVpnInstOpData(Long count, String vrfId) {
+        return new VpnInstanceOpDataEntryBuilder().setVpnInterfaceCount(count).setVrfId(vrfId).build();
+    }
+
+    static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
+        InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+        Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(broker, LogicalDatastoreType.OPERATIONAL, id);
+        if(vpnInstanceOpData.isPresent()) {
+            return vpnInstanceOpData.get();
+        }
+        return null;
+    }
+
     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
index 3dd6644554d671afff0f5336afe80d608b56f0d7..ce72eb6ac19489d155d874d14c16d2de680bb280 100644 (file)
@@ -130,7 +130,7 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager,
     @Override
     public void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label) {
         LOG.info("Adding extra route with destination {} and nexthop {}", destination, nextHop);
-        vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label);
+        vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label, null);
     }
 
     @Override
index bd0f22a35ccc89b300363e2421e298c2cda63e44..36ffe3d20e6c0a792c0e5bc4a69983a5def0a8d2 100644 (file)
@@ -144,4 +144,11 @@ public class InterfaceUtils {
     String[] split = portId.getValue().split(OF_URI_SEPARATOR);
     return split[1];
   }
+
+  public static BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
+    String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+    NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+    return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
+  }
+
 }