Vpnmanager and fibmanager changes 48/31948/1
authorDeepthi V V <deepthi.v.v@ericsson.com>
Wed, 30 Dec 2015 10:13:50 +0000 (15:43 +0530)
committerDeepthi V V <deepthi.v.v@ericsson.com>
Wed, 30 Dec 2015 10:15:45 +0000 (15:45 +0530)
1. Merge fib and nexthop manager
2. Integrate with interface manager, itm and arpmanager

Change-Id: I734355456a0d75df443e679763f6b4ab7f783f7f
Signed-off-by: Deepthi V V <deepthi.v.v@ericsson.com>
36 files changed:
features/pom.xml
features/src/main/features/features.xml
fibmanager/fibmanager-api/src/main/java/org/opendaylight/fibmanager/api/IFibManager.java
fibmanager/fibmanager-api/src/main/yang/l3nexthop.yang [new file with mode: 0644]
fibmanager/fibmanager-impl/pom.xml
fibmanager/fibmanager-impl/src/main/config/default-config.xml
fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/FibManager.java
fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/FibManagerProvider.java
fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/FibNodeCapableListener.java
fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/NexthopManager.java [new file with mode: 0644]
fibmanager/fibmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/fibmanager/impl/rev150325/FibmanagerImplModule.java
fibmanager/fibmanager-impl/src/main/yang/fibmanager-impl.yang
fibmanager/fibmanager-impl/src/test/java/org/opendaylight/vpnservice/fibmanager/test/FibManagerTest.java
fibmanager/pom.xml
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java
pom.xml
vpnmanager/vpnmanager-api/src/main/java/org/opendaylight/vpnmanager/api/IVpnManager.java
vpnmanager/vpnmanager-api/src/main/yang/l3vpn.yang
vpnmanager/vpnmanager-api/src/main/yang/odl-l3vpn.yang
vpnmanager/vpnmanager-impl/pom.xml
vpnmanager/vpnmanager-impl/src/main/config/default-config.xml
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/AbstractDataChangeListener.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/ArpNotificationHandler.java [new file with mode: 0644]
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/ArpReplyOrRequest.java [new file with mode: 0644]
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/InterfaceChangeListener.java [deleted file]
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/InterfaceStateChangeListener.java [new file with mode: 0644]
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/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 [new file with mode: 0644]
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpnservice/impl/rev150216/VpnserviceImplModule.java
vpnmanager/vpnmanager-impl/src/main/yang/vpnservice-impl.yang
vpnmanager/vpnmanager-impl/src/test/java/org/opendaylight/vpnservice/test/VpnServiceTest.java

index 80effa8f6cc9f30924dc4a5f8222dfdc4996ff05..e992726c6e3f00c159fbdb55a50161c70f9fe424 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+Copyright (c) 2015 - 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 INTERNAL
@@ -233,23 +233,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <artifactId>model-bgp</artifactId>
       <version>2013.07.15.8-SNAPSHOT</version>
     </dependency>
-    <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>nexthopmgr-impl</artifactId>
-      <version>${nexthopmgr.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>nexthopmgr-impl</artifactId>
-      <version>${nexthopmgr.version}</version>
-      <classifier>config</classifier>
-      <type>xml</type>
-    </dependency>
-    <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>nexthopmgr-api</artifactId>
-      <version>${nexthopmgr.version}</version>
-    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>fibmanager-impl</artifactId>
index fa5145bde394f2c9113cfb67a0bf1cadf8488164..99548a751e012370c9663c9dae172f319f5f3cbb 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- vi: set et smarttab sw=4 tabstop=4: -->
 <!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+Copyright (c) 2015 - 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,
@@ -30,7 +30,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <bundle>mvn:org.opendaylight.vpnservice/arputil-api/${arputil.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/alivenessmonitor-api/${vpnservices.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/vpnmanager-api/${vpnmanager.version}</bundle>
-    <bundle>mvn:org.opendaylight.vpnservice/nexthopmgr-api/${nexthopmgr.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/fibmanager-api/${fibmanager.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/itm-api/${itm.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/dhcpservice-api/${vpnservices.version}</bundle>
@@ -53,7 +52,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <bundle>mvn:org.opendaylight.vpnservice/interfacemgr-api/${interfacemgr.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/interfacemgr-impl/${interfacemgr.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}</bundle>
-    <bundle>mvn:org.opendaylight.vpnservice/nexthopmgr-impl/${nexthopmgr.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}</bundle>
@@ -70,7 +68,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <configfile finalname="arputil-impl-default-config.xml">mvn:org.opendaylight.vpnservice/arputil-impl/${arputil.version}/xml/config</configfile>
     <configfile finalname="alivenessmonitor-impl-default-config.xml">mvn:org.opendaylight.vpnservice/alivenessmonitor-impl/${vpnservices.version}/xml/config</configfile>
     <configfile finalname="vpnmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}/xml/config</configfile>
-    <configfile finalname="nexthopmgr-impl-default-config.xml">mvn:org.opendaylight.vpnservice/nexthopmgr-impl/${nexthopmgr.version}/xml/config</configfile>
     <configfile finalname="fibmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version}/xml/config</configfile>
     <configfile finalname="itm-impl-default-config.xml">mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}/xml/config</configfile>
     <configfile finalname="dhcpservice-impl-default-config.xml">mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}/xml/config</configfile>
index 595677f2376727ec16bfe6b4379c24c8e930ae93..213241ee5fc1817b9167a686e801c6236b583bf9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -9,8 +9,12 @@
 package org.opendaylight.fibmanager.api;
 
 import java.math.BigInteger;
+import java.util.List;
 
 public interface IFibManager {
     void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd);
     void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd);
+    List<String> printFibEntries();
+    void addStaticRoute(String prefix, String nextHop, String rd, int label);
+    void deleteStaticRoute(String prefix, String rd);
 }
diff --git a/fibmanager/fibmanager-api/src/main/yang/l3nexthop.yang b/fibmanager/fibmanager-api/src/main/yang/l3nexthop.yang
new file mode 100644 (file)
index 0000000..5daa68c
--- /dev/null
@@ -0,0 +1,32 @@
+module l3nexthop {
+    namespace "urn:opendaylight:vpnservice:l3nexthop";
+    prefix l3nexthop;
+
+    revision "2015-04-09" {
+        description "L3 NextHop module";
+    }
+
+    container l3nexthop {
+        config false;
+        list vpnNexthops{
+            key "vpnId";
+            leaf vpnId {type uint32;}
+            list vpnNexthop{
+                key  "IpAddress";
+                leaf IpAddress {type string;}
+                leaf egressPointer {type uint32;}
+                leaf dpnId {type uint64;}
+                leaf flowrefCount {type uint16; }
+            }
+        }
+        list tunnelNexthops{
+            key "dpnId";
+            leaf dpnId {type uint64;}
+            list tunnelNexthop{
+                key  "IpAddress";
+                leaf IpAddress {type string;}
+                leaf egressPointer {type uint32;}
+            }
+        }
+    }
+}
\ No newline at end of file
index 762f101a69f84d95380ef7d00266e64ffbc5e388..bc0ee25a604ae8e31cb67399d58b4bdd740b5568 100644 (file)
@@ -33,8 +33,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     </dependency>
     <dependency>
       <groupId>org.opendaylight.vpnservice</groupId>
-      <artifactId>vpnmanager-impl</artifactId>
-      <version>${vpnservices.version}</version>
+      <artifactId>itm-api</artifactId>
+      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.vpnservice</groupId>
@@ -43,7 +43,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     </dependency>
     <dependency>
       <groupId>org.opendaylight.vpnservice</groupId>
-      <artifactId>nexthopmgr-api</artifactId>
+      <artifactId>idmanager-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>interfacemgr-api</artifactId>
       <version>${vpnservices.version}</version>
     </dependency>
     <dependency>
index ebf0531b3ec7a97ec92ad656310629165692e399..0656c724f55fc630ab7923e0938bb2d276836cfe 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- vi: set et smarttab sw=4 tabstop=4: -->
 <!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+Copyright (c) 2015 - 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,
@@ -25,6 +25,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <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>
+          <rpcregistry>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+            <name>binding-rpc-broker</name>
+          </rpcregistry>
           <mdsalutil>
             <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
             <name>mdsalutil-service</name>
index e38c84deeec6a11e59bab4d32b18506aa5dfc933..ef2bec3acff24a147ec50d771e83ac85e7b49584 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -11,14 +11,14 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-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.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
@@ -26,7 +26,8 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.vpnmanager.api.IVpnManager;
-import org.opendaylight.vpnservice.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
 import org.opendaylight.vpnservice.mdsalutil.ActionType;
 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
@@ -38,23 +39,26 @@ import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
+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.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.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.GetEgressPointerInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.GetEgressPointerOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthopService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.RemoveLocalNextHopInputBuilder;
+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.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -63,15 +67,22 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   private static final String FLOWID_PREFIX = "L3.";
   private ListenerRegistration<DataChangeListener> listenerRegistration;
   private final DataBroker broker;
-  private final L3nexthopService l3nexthopService;
   private IMdsalApiManager mdsalManager;
   private IVpnManager vpnmanager;
+  private NexthopManager nextHopManager;
+  private ItmRpcService itmManager;
+  private OdlInterfaceRpcService interfaceManager;
 
   private static final short L3_FIB_TABLE = 21;
   private static final short L3_LFIB_TABLE = 20;
+  private static final short L3_PROTOCOL_TABLE = 36;
+  private static final short L3_INTERFACE_TABLE = 80;
+  public static final short LPORT_DISPATCHER_TABLE = 30;
   private static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);
   private static final BigInteger COOKIE_VM_FIB_TABLE =  new BigInteger("8000003", 16);
   private static final int DEFAULT_FIB_FLOW_PRIORITY = 10;
+  private static final BigInteger METADATA_MASK_CLEAR = new BigInteger("000000FFFFFFFFFF", 16);
+  private static final BigInteger CLEAR_METADATA = BigInteger.valueOf(0);
 
 
   private static final FutureCallback<Void> DEFAULT_CALLBACK =
@@ -85,10 +96,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
         };
       };
 
-  public FibManager(final DataBroker db, final RpcService nextHopService) {
+  public FibManager(final DataBroker db) {
     super(VrfEntry.class);
     broker = db;
-    l3nexthopService = (L3nexthopService)nextHopService;
     registerListener(db);
   }
 
@@ -105,6 +115,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     LOG.info("Fib Manager Closed");
   }
 
+  public void setNextHopManager(NexthopManager nextHopManager) {
+    this.nextHopManager = nextHopManager;
+  }
 
   public void setMdsalManager(IMdsalApiManager mdsalManager) {
     this.mdsalManager = mdsalManager;
@@ -114,6 +127,14 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     this.vpnmanager = vpnmanager;
   }
 
+  public void setITMRpcService(ItmRpcService itmManager) {
+      this.itmManager = itmManager;
+  }
+  
+  public void setInterfaceManager(OdlInterfaceRpcService ifManager) {
+      this.interfaceManager = ifManager;
+  }
+
   private void registerListener(final DataBroker db) {
     try {
       listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
@@ -166,6 +187,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   @Override
   protected void update(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update) {
     LOG.trace("key: " + identifier + ", original=" + original + ", update=" + update );
+    createFibEntries(identifier, update);
   }
 
   private void createFibEntries(final InstanceIdentifier<VrfEntry> identifier,
@@ -174,40 +196,161 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     Preconditions.checkNotNull(vrfTableKey, "VrfTablesKey cannot be null or empty!");
     Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
 
-    Long vpnId = getVpnId(vrfTableKey.getRouteDistinguisher());
-    Preconditions.checkNotNull(vpnId, "Vpn Instance not available!");
-    Collection<BigInteger> dpns = vpnmanager.getDpnsForVpn(vpnId);
-    for (BigInteger dpId : dpns) {
-      addRouteInternal(dpId, vpnId, vrfTableKey, vrfEntry);
+    VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+    Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available!");
+    Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId() + "has null vpnId!");
+
+    Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+    if (vpnToDpnList != null) {
+      BigInteger localDpnId = createLocalFibEntry(vpnInstance.getVpnId(),
+                          vrfTableKey.getRouteDistinguisher(), vrfEntry);
+      for (VpnToDpnList curDpn : vpnToDpnList) {
+        if (!curDpn.getDpnId().equals(localDpnId)) {
+          createRemoteFibEntry(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(),
+                               vrfTableKey, vrfEntry);
+        }
+      }
     }
   }
 
-  private void addRouteInternal(final BigInteger dpId, final long vpnId, final VrfTablesKey vrfTableKey,
-                                final VrfEntry vrfEntry) {
+  public BigInteger createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
+    BigInteger localDpnId = BigInteger.ZERO;
+    Prefixes localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
+    boolean staticRoute = false;
+
+    //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;
+    }
+
+    if(localNextHopInfo != null) {
+      localDpnId = localNextHopInfo.getDpnId();
+      long groupId = nextHopManager.createLocalNextHop(vpnId, localDpnId, localNextHopInfo.getVpnInterfaceName(),
+                                                        (staticRoute == true) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix());
+      List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
+
+      actionInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
+
+      makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, actionInfos, NwConstants.ADD_FLOW);
+      makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), groupId, vrfEntry.getNextHopAddress(), NwConstants.ADD_FLOW);
+
+      LOG.debug("Installing tunnel table entry on dpn {} for interface {} with label {}", 
+                      localDpnId, localNextHopInfo.getVpnInterfaceName(), vrfEntry.getLabel());
+      makeTunnelTableEntry(localDpnId, vrfEntry.getLabel(), groupId);
+
+    }
+    return localDpnId;
+  }
+
+  private void makeTunnelTableEntry(BigInteger dpId, long label, long groupId/*String egressInterfaceName*/) {
+      List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+      actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
+
+
+      createTerminatingServiceActions(dpId, (int)label, actionsInfos);
+
+      LOG.debug("Terminating service Entry for dpID {} : label : {} egress : {} installed successfully {}",
+              dpId, label, groupId);
+  }
+
+  public void createTerminatingServiceActions( BigInteger destDpId, int label, List<ActionInfo> actionsInfos) {
+    // FIXME
+/*      List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+
+      LOG.info("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", destDpId , label,actionsInfos);
+
+      // Matching metadata
+      mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
+                                  MetaDataUtil.getTunnelIdWithValidVniBitAndVniSet(label),
+                                  MetaDataUtil.METADA_MASK_TUNNEL_ID }));
+
+      List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+      mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+
+      FlowEntity terminatingServiceTableFlowEntity = MDSALUtil.buildFlowEntity(destDpId,ITMConstants.TERMINATING_SERVICE_TABLE,
+                      getFlowRef(destDpId, ITMConstants.TERMINATING_SERVICE_TABLE,label), 5, String.format("%s:%d","TST Flow Entry ",label),
+                      0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(label)),mkMatches, mkInstructions);
+
+      mdsalManager.installFlow(terminatingServiceTableFlowEntity);*/
+ }
+
+  private void removeTunnelTableEntry(BigInteger dpId, long label) {
+      // FIXME
+      // itmManager.removeTerminatingServiceAction(dpId, (int)label);
+
+      // LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}",dpId, label);
+  }
+
+  public BigInteger deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
+    BigInteger localDpnId = BigInteger.ZERO;
+    VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
+    boolean staticRoute = false;
+
+    //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;
+    }
+
+    if(localNextHopInfo != null) {
+      localDpnId = localNextHopInfo.getDpnId();
+      if (getPrefixToInterface(vpnId, (staticRoute == true) ? vrfEntry.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());
+      }
+    }
+    return localDpnId;
+  }
+
+  private InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(Long vpnId, String ipPrefix) {
+    return InstanceIdentifier.builder(PrefixToInterface.class)
+        .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
+  }
+
+  private Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
+    Optional<Prefixes> localNextHopInfoData =
+        read(LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
+    return  localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
+  }
+
+  private void createRemoteFibEntry(final BigInteger localDpnId, final BigInteger remoteDpnId,
+                                    final long vpnId, final VrfTablesKey vrfTableKey,
+                                    final VrfEntry vrfEntry) {
     String rd = vrfTableKey.getRouteDistinguisher();
     LOG.debug("adding route " + vrfEntry.getDestPrefix() + " " + rd);
 
-    GetEgressPointerOutput adjacency = resolveAdjacency(dpId, vpnId, vrfEntry);
-    long groupId = -1;
-    boolean isLocalRoute = false;
-    if(adjacency != null) {
-      groupId = adjacency.getEgressPointer();
-      isLocalRoute = adjacency.isLocalDestination();
-    }
-    if(groupId == -1) {
+    List<ActionInfo> actionInfos = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+    if(actionInfos == null) {
       LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
                                    vrfEntry.getNextHopAddress(), rd);
       LOG.warn("Failed to add Route: {} in vpn: {}",
                              vrfEntry.getDestPrefix(), rd);
       return;
     }
-
-    makeConnectedRoute(dpId, vpnId, vrfEntry, rd, groupId, NwConstants.ADD_FLOW);
-
-    if (isLocalRoute) {
-      makeLFibTableEntry(dpId, vrfEntry.getLabel(), groupId, vrfEntry.getNextHopAddress(), NwConstants.ADD_FLOW);
+    BigInteger dpnId = nextHopManager.getDpnForPrefix(vpnId, vrfEntry.getDestPrefix());
+    if(dpnId == null) {
+        //This route may be extra route... try to query with nexthop Ip
+        LOG.debug("Checking for extra route to install remote fib entry {}", vrfEntry.getDestPrefix());
+        dpnId = nextHopManager.getDpnForPrefix(vpnId, vrfEntry.getNextHopAddress() + "/32");
+    }
+    if(dpnId == null) {
+        LOG.debug("Push label action for prefix {}", vrfEntry.getDestPrefix());
+        actionInfos.add(new ActionInfo(ActionType.push_mpls, new String[] { null }));
+        actionInfos.add(new ActionInfo(ActionType.set_field_mpls_label, new String[] { Long.toString(vrfEntry.getLabel())}));
+    } else {
+        int label = vrfEntry.getLabel().intValue();
+        LOG.debug("adding set tunnel id action for label {}", label);
+        actionInfos.add(new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+                MetaDataUtil.getTunnelIdWithValidVniBitAndVniSet(label),
+                MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
     }
 
+    makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, actionInfos, NwConstants.ADD_FLOW);
     LOG.debug(
         "Successfully added fib entry for " + vrfEntry.getDestPrefix() + " vpnId " + vpnId);
   }
@@ -218,40 +361,36 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     Preconditions.checkNotNull(vrfTableKey, "VrfTablesKey cannot be null or empty!");
     Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
 
-    Long vpnId = getVpnId(vrfTableKey.getRouteDistinguisher());
-    Preconditions.checkNotNull(vpnId, "Vpn Instance not available!");
-    Collection<BigInteger> dpns = vpnmanager.getDpnsForVpn(vpnId);
-    for (BigInteger dpId : dpns) {
-      deleteRoute(dpId, vpnId, vrfTableKey, vrfEntry);
+    VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+    Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available!");
+    Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+    if (vpnToDpnList != null) {
+      BigInteger localDpnId = deleteLocalFibEntry(vpnInstance.getVpnId(),
+                          vrfTableKey.getRouteDistinguisher(), vrfEntry);
+      for (VpnToDpnList curDpn : vpnToDpnList) {
+        if (!curDpn.getDpnId().equals(localDpnId)) {
+          deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry);
+        }
+      }
+
     }
   }
 
-  public void deleteRoute(final BigInteger dpId, final long vpnId, final VrfTablesKey vrfTableKey,
-                          final VrfEntry vrfEntry) {
+  public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
+                                final long vpnId, final VrfTablesKey vrfTableKey,
+                                final VrfEntry vrfEntry) {
     LOG.debug("deleting route "+ vrfEntry.getDestPrefix() + " "+vpnId);
     String rd = vrfTableKey.getRouteDistinguisher();
-    GetEgressPointerOutput adjacency = resolveAdjacency(dpId, vpnId, vrfEntry);
-    long groupId = -1;
-    boolean isLocalRoute = false;
-    if(adjacency != null) {
-      groupId = adjacency.getEgressPointer();
-      isLocalRoute = adjacency.isLocalDestination();
-    }
-    if(groupId == -1) {
+    List<ActionInfo> actionInfos = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+    if(actionInfos == null) {
       LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
-                              vrfEntry.getNextHopAddress(), rd);
-      LOG.warn("Failed to add Route: {} in vpn: {}",
-                             vrfEntry.getDestPrefix(), rd);
+                vrfEntry.getNextHopAddress(), rd);
+      LOG.warn("Failed to delete Route: {} in vpn: {}",
+               vrfEntry.getDestPrefix(), rd);
       return;
     }
 
-    makeConnectedRoute(dpId, vpnId, vrfEntry, rd, groupId, NwConstants.DEL_FLOW);
-
-    if (isLocalRoute) {
-      makeLFibTableEntry(dpId, vrfEntry.getLabel(), groupId, vrfEntry.getNextHopAddress(), NwConstants.DEL_FLOW);
-      deleteLocalAdjacency(dpId, vpnId, vrfEntry);
-    }
-
+    makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW);
     LOG.debug("Successfully delete fib entry for "+ vrfEntry.getDestPrefix() + " vpnId "+vpnId);
   }
 
@@ -261,11 +400,11 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   }
 
   private void makeConnectedRoute(BigInteger dpId, long vpnId, VrfEntry vrfEntry, String rd,
-                                  long groupId, int addOrRemove) {
+                                  List<ActionInfo> actionInfos, int addOrRemove) {
     LOG.trace("makeConnectedRoute: vrfEntry {}",vrfEntry);
     String values[] = vrfEntry.getDestPrefix().split("/");
     String ipAddress = values[0];
-    int prefixLength = (values.length == 1) ? 32 : Integer.parseInt(values[1]);
+    int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
     LOG.debug("Adding route to DPN. ip {} masklen {}", ipAddress, prefixLength);
     InetAddress destPrefix = null;
     try {
@@ -289,13 +428,8 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     }
 
     List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
-    List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
-
     if(addOrRemove == NwConstants.ADD_FLOW) {
-      actionsInfos.add(new ActionInfo(ActionType.push_mpls, new String[] { null }));
-      actionsInfos.add(new ActionInfo(ActionType.set_field_mpls_label, new String[] { Long.toString(vrfEntry.getLabel())}));
-      actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
-      instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+      instructions.add(new InstructionInfo(InstructionType.write_actions, actionInfos));
     }
 
     String flowRef = getFlowRef(dpId, L3_FIB_TABLE, rd, destPrefix);
@@ -308,8 +442,17 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                                            COOKIE_VM_FIB_TABLE, matches, instructions);
 
     if (addOrRemove == NwConstants.ADD_FLOW) {
+      /* We need to call sync API to install flow so that 2 DS operations on the same object do not
+      * happen at same time. However, MDSALManager's syncInstallFlow takes a delay time (or uses a default one) to wait
+      * 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);
     } else {
+      // FIXME: sync calls.
+      // mdsalManager.syncRemoveFlow(flowEntity, 1);
       mdsalManager.removeFlow(flowEntity);
     }
   }
@@ -323,6 +466,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
     List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
     List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+    actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
     actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
     instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
 
@@ -335,29 +479,28 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                                            COOKIE_VM_LFIB_TABLE, matches, instructions);
 
     if (addOrRemove == NwConstants.ADD_FLOW) {
+      /* We need to call sync API to install flow so that 2 DS operations on the same object do not
+      * happen at same time. However, MDSALManager's syncInstallFlow takes a delay time (or uses a default one) to wait
+      * 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:
+      // mdsalManager.syncInstallFlow(flowEntity, 1);
       mdsalManager.installFlow(flowEntity);
     } else {
+      // FIXME:
+      // mdsalManager.syncRemoveFlow(flowEntity, 1);
       mdsalManager.removeFlow(flowEntity);
     }
     LOG.debug("LFIB Entry for dpID {} : label : {} group {} modified successfully {}",dpId, label, groupId );
   }
 
-  private void deleteLocalAdjacency(final BigInteger dpId, final long vpnId, final VrfEntry vrfEntry) {
-    LOG.trace("deleteLocalAdjacency called with dpid {}, vpnId{}, VrfEntry {}",dpId, vpnId, vrfEntry);;
+  private void deleteLocalAdjacency(final BigInteger dpId, final long vpnId, final String ipAddress) {
+    LOG.trace("deleteLocalAdjacency called with dpid {}, vpnId{}, ipAddress {}",dpId, vpnId, ipAddress);
     try {
-      Future<RpcResult<Void>> result =
-          l3nexthopService.removeLocalNextHop(new RemoveLocalNextHopInputBuilder().setDpnId(dpId)
-                                                  .setIpPrefix(vrfEntry.getDestPrefix())
-                                                  .setNexthopIp(vrfEntry.getNextHopAddress())
-                                                  .setVpnId(vpnId)
-                                                  .build());
-      RpcResult<Void> rpcResult = result.get();
-      if (rpcResult.isSuccessful()) {
-        LOG.debug("Local Next hop for {} on dpn {} successfully deleted", vrfEntry.getDestPrefix(), dpId);
-      } else {
-        LOG.error("Local Next hop for {} on dpn {} not deleted", vrfEntry.getDestPrefix(), dpId);
-      }
-    } catch (NullPointerException | InterruptedException | ExecutionException e) {
+      nextHopManager.removeLocalNextHop(dpId, vpnId, ipAddress);
+    } catch (NullPointerException e) {
       LOG.trace("", e);
     }
   }
@@ -368,7 +511,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     Optional<VrfTables> vrfTable = read(LogicalDatastoreType.OPERATIONAL, id);
     if(vrfTable.isPresent()) {
       for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
-        addRouteInternal(dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+        // Passing null as we don't know the dpn
+        // to which prefix is attached at this point
+        createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
       }
     }
   }
@@ -379,7 +524,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     Optional<VrfTables> vrfTable = read(LogicalDatastoreType.OPERATIONAL, id);
     if(vrfTable.isPresent()) {
       for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
-        deleteRoute(dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+        // Passing null as we don't know the dpn
+        // to which prefix is attached at this point
+        deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
       }
     }
   }
@@ -405,60 +552,43 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
         .append(destPrefix.getHostAddress()).toString();
   }
 
-  protected GetEgressPointerOutput resolveAdjacency(final BigInteger dpId, final long vpnId,
-                        final VrfEntry vrfEntry) {
-    GetEgressPointerOutput adjacency = null;
-    LOG.trace("resolveAdjacency called with dpid {}, vpnId{}, VrfEntry {}",dpId, vpnId, vrfEntry);;
+  protected List<ActionInfo> resolveAdjacency(final BigInteger localDpnId, final BigInteger remoteDpnId,
+                                              final long vpnId, final VrfEntry vrfEntry) {
+    List<ActionInfo> adjacency = null;
+    LOG.trace("resolveAdjacency called with localdpid{} remotedpid {}, vpnId{}, VrfEntry {}", localDpnId, remoteDpnId, vpnId, vrfEntry);;
     try {
-      Future<RpcResult<GetEgressPointerOutput>> result =
-          l3nexthopService.getEgressPointer(new GetEgressPointerInputBuilder().setDpnId(dpId)
-                                                .setIpPrefix(vrfEntry.getDestPrefix())
-                                                .setNexthopIp(vrfEntry.getNextHopAddress())
-                                                .setVpnId(vpnId)
-                                                .build());
-      RpcResult<GetEgressPointerOutput> rpcResult = result.get();
-      if (rpcResult.isSuccessful()) {
-        adjacency = rpcResult.getResult();
-      } else {
-        LOG.error("Next hop information not available");
-      }
-    } catch (NullPointerException | InterruptedException | ExecutionException e) {
+      adjacency =
+          nextHopManager.getRemoteNextHopPointer(localDpnId, remoteDpnId, vpnId,
+                                                 vrfEntry.getDestPrefix(),
+                                                 vrfEntry.getNextHopAddress());
+    } catch (NullPointerException e) {
       LOG.trace("", e);
     }
     return adjacency;
   }
 
-  protected Long getVpnId(String rd) {
-    Long vpnId = null;
-    InstanceIdentifier<VpnInstances> id = InstanceIdentifier.create(VpnInstances.class);
-    Optional<VpnInstances> vpnInstances = read(LogicalDatastoreType.OPERATIONAL, id);
-    if(vpnInstances.isPresent()) {
-      List<VpnInstance> vpns = vpnInstances.get().getVpnInstance();
-      for(VpnInstance vpn : vpns) {
-        if(vpn.getIpv4Family().getRouteDistinguisher().equals(rd)) {
-          VpnInstance1 vpnInstanceId = vpn.getAugmentation(VpnInstance1.class);
-          if (vpnInstanceId != null) {
-            vpnId = vpnInstanceId.getVpnId();
-            break;
-          }
-        }
-      }
+  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);
+    if(vpnInstanceOpData.isPresent()) {
+      return vpnInstanceOpData.get();
     }
-    return vpnId;
+    return null;
   }
 
     public void processNodeAdd(BigInteger dpnId) {
         LOG.debug("Received notification to install TableMiss entries for dpn {} ", dpnId);
         makeTableMissFlow(dpnId, NwConstants.ADD_FLOW);
+        makeProtocolTableFlow(dpnId, NwConstants.ADD_FLOW);
+        makeL3IntfTblMissFlow(dpnId, NwConstants.ADD_FLOW);
     }
 
     private void makeTableMissFlow(BigInteger dpnId, int addOrRemove) {
         final BigInteger COOKIE_TABLE_MISS = new BigInteger("1030000", 16);
-        // Instruction to punt to controller
+        // Instruction to goto L3 InterfaceTable
         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
-        List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
-        actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
-        instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+        instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { L3_INTERFACE_TABLE }));
         List<MatchInfo> matches = new ArrayList<MatchInfo>();
         FlowEntity flowEntityLfib = MDSALUtil.buildFlowEntity(dpnId, L3_LFIB_TABLE,
                 getFlowRef(dpnId, L3_LFIB_TABLE, NwConstants.TABLE_MISS_FLOW),
@@ -484,4 +614,76 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                 .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(tableMiss)
                 .append(FLOWID_PREFIX).toString();
     }
+
+  /*
+   * Install flow entry in protocol table to forward mpls
+   * coming through gre tunnel to LFIB table.
+   */
+  private void makeProtocolTableFlow(BigInteger dpnId, int addOrRemove) {
+    final BigInteger COOKIE_PROTOCOL_TABLE = new BigInteger("1070000", 16);
+    // Instruction to goto L3 InterfaceTable
+    List<InstructionInfo> instructions = new ArrayList<>();
+    instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {L3_LFIB_TABLE}));
+    List<MatchInfo> matches = new ArrayList<MatchInfo>();
+    matches.add(new MatchInfo(MatchFieldType.eth_type,
+                              new long[] { 0x8847L }));
+    FlowEntity flowEntityToLfib = MDSALUtil.buildFlowEntity(dpnId, L3_PROTOCOL_TABLE,
+                                                          getFlowRef(dpnId, L3_PROTOCOL_TABLE,
+                                                                     L3_LFIB_TABLE),
+                                                          DEFAULT_FIB_FLOW_PRIORITY,
+                                                          "Protocol Table For LFIB",
+                                                          0, 0,
+                                                          COOKIE_PROTOCOL_TABLE,
+                                                          matches, instructions);
+
+    if (addOrRemove == NwConstants.ADD_FLOW) {
+      LOG.debug("Invoking MDSAL to install Protocol Entries for dpn {}", dpnId);
+      mdsalManager.installFlow(flowEntityToLfib);
+    } else {
+      mdsalManager.removeFlow(flowEntityToLfib);
+    }
+  }
+
+  public List<String> printFibEntries() {
+    List<String> result = new ArrayList<String>();
+    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);
+    if (fibEntries.isPresent()) {
+      List<VrfTables> vrfTables = fibEntries.get().getVrfTables();
+      for (VrfTables vrfTable : vrfTables) {
+        for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
+          result.add(String.format("   %-7s  %-20s  %-20s  %-7s", vrfTable.getRouteDistinguisher(),
+                  vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddress(), vrfEntry.getLabel()));
+        }
+      }
+    }
+    return result;
+  }
+
+  private void makeL3IntfTblMissFlow(BigInteger dpnId, int addOrRemove) {
+    List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+    List<MatchInfo> matches = new ArrayList<MatchInfo>();
+    final BigInteger COOKIE_TABLE_MISS = new BigInteger("1030000", 16);
+    // Instruction to clear metadata except SI and LportTag bits
+    instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] {
+                    CLEAR_METADATA, METADATA_MASK_CLEAR }));
+    // Instruction to clear action
+    instructions.add(new InstructionInfo(InstructionType.clear_actions));
+    // Instruction to goto L3 InterfaceTable
+
+    instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { LPORT_DISPATCHER_TABLE }));
+
+    FlowEntity flowEntityL3Intf = MDSALUtil.buildFlowEntity(dpnId, L3_INTERFACE_TABLE,
+            getFlowRef(dpnId, L3_INTERFACE_TABLE, NwConstants.TABLE_MISS_FLOW),
+            NwConstants.TABLE_MISS_PRIORITY, "L3 Interface Table Miss", 0, 0, COOKIE_TABLE_MISS, matches, instructions);
+    if (addOrRemove == NwConstants.ADD_FLOW) {
+      LOG.info("Invoking MDSAL to install L3 interface Table Miss Entries");
+      mdsalManager.installFlow(flowEntityL3Intf);
+    } else {
+      mdsalManager.removeFlow(flowEntityL3Intf);
+    }
+  }
+
 }
index ef16ec09ba6ba3ea580c328c1145afbe9e091c97..7d457708da77b2174498017a6e28dc7055cab317 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -8,14 +8,16 @@
 package org.opendaylight.vpnservice.fibmanager;
 
 import java.math.BigInteger;
+import java.util.List;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.fibmanager.api.IFibManager;
 import org.opendaylight.vpnmanager.api.IVpnManager;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthopService;
-import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -26,18 +28,29 @@ public class FibManagerProvider implements BindingAwareProvider, IFibManager, Au
   private FibManager fibManager;
   private IMdsalApiManager mdsalManager;
   private IVpnManager vpnmanager;
-  //private FibNodeCapableListener fibNcListener;
+  private NexthopManager nexthopManager;
+  private IdManagerService idManager;
+  private ItmRpcService itmManager;
+  private OdlInterfaceRpcService interfaceManager;
+  private FibNodeCapableListener fibNcListener;
 
   @Override
   public void onSessionInitiated(ProviderContext session) {
     LOG.info("FibManagerProvider Session Initiated");
     try {
       final  DataBroker dataBroker = session.getSALService(DataBroker.class);
-      final RpcService nexthopService = session.getRpcService(L3nexthopService.class);
-      fibManager = new FibManager(dataBroker, nexthopService);
+      nexthopManager = new NexthopManager(dataBroker);
+      nexthopManager.setMdsalManager(mdsalManager);
+      nexthopManager.setIdManager(idManager);
+      nexthopManager.setInterfaceManager(interfaceManager);
+      nexthopManager.setITMRpcService(itmManager);
+      fibManager = new FibManager(dataBroker);
       fibManager.setMdsalManager(mdsalManager);
       fibManager.setVpnmanager(vpnmanager);
-      //fibNcListener = new FibNodeCapableListener(dataBroker, fibManager);
+      fibManager.setNextHopManager(nexthopManager);
+      fibManager.setITMRpcService(itmManager);
+      fibManager.setInterfaceManager(interfaceManager);
+      fibNcListener = new FibNodeCapableListener(dataBroker, fibManager);
     } catch (Exception e) {
       LOG.error("Error initializing services", e);
     }
@@ -47,7 +60,7 @@ public class FibManagerProvider implements BindingAwareProvider, IFibManager, Au
   public void close() throws Exception {
     LOG.info("FibManagerProvider Closed");
     fibManager.close();
-    //fibNcListener.close();
+    fibNcListener.close();
   }
 
   public void setMdsalManager(IMdsalApiManager mdsalManager) {
@@ -59,6 +72,18 @@ public class FibManagerProvider implements BindingAwareProvider, IFibManager, Au
     vpnmanager.setFibService(this);
   }
 
+  public void setIdManager(IdManagerService idManager) {
+    this.idManager = idManager;
+  }
+
+  public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+    this.interfaceManager = interfaceManager;
+  }
+
+  public void setITMProvider(ItmRpcService itmManager) {
+    this.itmManager = itmManager;
+  }
+
   @Override
   public void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd) {
     fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
@@ -68,4 +93,20 @@ public class FibManagerProvider implements BindingAwareProvider, IFibManager, Au
   public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd) {
     fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
   }
+
+  @Override
+  public List<String> printFibEntries() {
+    return fibManager.printFibEntries();
+  }
+
+  //Temp
+  @Override
+  public void addStaticRoute(String prefix, String nextHop, String rd, int label) {
+    this.vpnmanager.addExtraRoute(prefix, nextHop, rd, null, label);
+  }
+
+  @Override
+  public void deleteStaticRoute(String prefix, String rd) {
+    this.vpnmanager.delExtraRoute(prefix, rd, null);
+  }
 }
index 7ea5281d611621e29070cc5c85f9abf62de59e68..74eef15944799f2f809d97e1a1d831b899ca6da1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -14,7 +14,7 @@ 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.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.vpnservice.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
diff --git a/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/NexthopManager.java b/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/vpnservice/fibmanager/NexthopManager.java
new file mode 100644 (file)
index 0000000..b762ced
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2015 - 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.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
+import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+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.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.GetTunnelInterfaceIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.GetTunnelInterfaceIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+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;
+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.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthops;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+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 NexthopManager implements AutoCloseable {
+    private static final Logger LOG = LoggerFactory.getLogger(NexthopManager.class);
+    private final DataBroker broker;
+    private IMdsalApiManager mdsalManager;
+    private OdlInterfaceRpcService interfaceManager;
+    private ItmRpcService itmManager;
+    private IdManagerService idManager;
+    private static final short LPORT_INGRESS_TABLE = 0;
+    private static final short LFIB_TABLE = 20;
+    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 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);
+            };
+        };
+
+    /**
+    * Provides nexthop functions
+    * Creates group ID pool
+    *
+    * @param db - dataBroker reference
+    */
+    public NexthopManager(final DataBroker db) {
+        broker = db;
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("NextHop Manager Closed");
+    }
+
+    public void setInterfaceManager(OdlInterfaceRpcService ifManager) {
+        this.interfaceManager = ifManager;
+    }
+
+    public void setMdsalManager(IMdsalApiManager mdsalManager) {
+        this.mdsalManager = mdsalManager;
+    }
+
+    public void setIdManager(IdManagerService idManager) {
+        this.idManager = idManager;
+        createNexthopPointerPool();
+    }
+
+    public void setITMRpcService(ItmRpcService itmManager) {
+        this.itmManager = itmManager;
+    }
+
+    protected void createNexthopPointerPool() {
+        CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+            .setPoolName(NEXTHOP_ID_POOL_NAME)
+            .setLow(150000L)
+            .setHigh(175000L)
+            .build();
+        //TODO: Error handling
+        Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+        LOG.trace("NextHopPointerPool result : {}", result);
+    }
+
+    private BigInteger getDpnId(String ofPortId) {
+        String[] fields = ofPortId.split(":");
+        BigInteger dpn = new BigInteger(fields[1]);
+        LOG.debug("DpnId: {}", dpn);
+        return dpn;
+    }
+
+    private String getNextHopKey(long vpnId, String ipAddress){
+        String nhKey = new String("nexthop." + vpnId + ipAddress);
+        return nhKey;
+    }
+
+    private String getNextHopKey(String ifName, String ipAddress){
+        String nhKey = new String("nexthop." + ifName + ipAddress);
+        return nhKey;
+    }
+
+    protected long createNextHopPointer(String nexthopKey) {
+        AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+            .setPoolName(NEXTHOP_ID_POOL_NAME).setIdKey(nexthopKey)
+            .build();
+        //TODO: Proper error handling once IdManager code is complete
+        try {
+            Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+            RpcResult<AllocateIdOutput> rpcResult = result.get();
+            return rpcResult.getResult().getIdValue();
+        } catch (NullPointerException | InterruptedException | ExecutionException e) {
+            LOG.trace("",e);
+        }
+        return 0;
+    }
+
+    protected void removeNextHopPointer(String nexthopKey) {
+        ReleaseIdInput idInput = new ReleaseIdInputBuilder().
+                                       setPoolName(NEXTHOP_ID_POOL_NAME)
+                                       .setIdKey(nexthopKey).build();
+        try {
+            Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+            RpcResult<Void> rpcResult = result.get();
+            if(!rpcResult.isSuccessful()) {
+                LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Exception when getting Unique Id for key {}", nexthopKey, e);
+        }
+    }
+
+    protected List<ActionInfo> getEgressActionsForInterface(String ifName) {
+        List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+        try {
+            Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+                interfaceManager.getEgressActionsForInterface(
+                    new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build());
+            RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+            if(!rpcResult.isSuccessful()) {
+                LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors());
+            } else {
+                List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions =
+                    rpcResult.getResult().getAction();
+                for (Action action : actions) {
+                    org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction();
+                    if (actionClass instanceof OutputActionCase) {
+                        listActionInfo.add(new ActionInfo(ActionType.output,
+                                                          new String[] {((OutputActionCase)actionClass).getOutputAction()
+                                                                            .getOutputNodeConnector().getValue()}));
+                    } else if (actionClass instanceof PushVlanActionCase) {
+                        listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
+                    } else if (actionClass instanceof SetFieldCase) {
+                        if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) {
+                            int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue();
+                            listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
+                                                              new String[] { Long.toString(vlanVid) }));
+                        }
+                    }
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Exception when egress actions for interface {}", ifName, e);
+        }
+        return listActionInfo;
+    }
+
+    protected Integer getTunnelInterfaceId(BigInteger srcDpId, BigInteger dstDpId) {
+        // FIXME: Enable during itm integration
+        /*
+        try {
+            Future<RpcResult<GetTunnelInterfaceIdOutput>> result = itmManager.getTunnelInterfaceId(new GetTunnelInterfaceIdInputBuilder()
+                                                                                 .setSourceDpid(srcDpId)
+                                                                                 .setDestinationDpid(dstDpId).build());
+            RpcResult<GetTunnelInterfaceIdOutput> rpcResult = result.get();
+            if(!rpcResult.isSuccessful()) {
+                LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
+            } else {
+                return rpcResult.getResult().getInterfaceid();
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and  {}", srcDpId, dstDpId, e);
+        }
+        */
+        return null;
+    }
+
+    public long createLocalNextHop(long vpnId, BigInteger dpnId,
+                                   String ifName, String ipAddress) {
+        long groupId = createNextHopPointer(getNextHopKey(vpnId, ipAddress));
+        String nextHopLockStr = new String(vpnId + ipAddress);
+        synchronized (nextHopLockStr.intern()) {
+            VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress);
+            LOG.trace("nexthop: {}", nexthop);
+            if (nexthop == null) {
+                Optional<Adjacency> adjacencyData =
+                        read(LogicalDatastoreType.OPERATIONAL, getAdjacencyIdentifier(ifName, ipAddress));
+                String macAddress = adjacencyData.isPresent() ? adjacencyData.get().getMacAddress() : null;
+                List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+                List<ActionInfo> listActionInfo = getEgressActionsForInterface(ifName);
+                BucketInfo bucket = new BucketInfo(listActionInfo);
+                // MAC re-write
+                if (macAddress != null) {
+                    listActionInfo.add(0, new ActionInfo(ActionType.set_field_eth_dest, new String[]{macAddress}));
+                    //listActionInfo.add(0, new ActionInfo(ActionType.pop_mpls, new String[]{}));
+                } else {
+                    //FIXME: Log message here.
+                    LOG.debug("mac address for new local nexthop is null");
+                }
+                listBucketInfo.add(bucket);
+                GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+                        dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo);
+
+                //update MD-SAL DS
+                addVpnNexthopToDS(dpnId, vpnId, ipAddress, groupId);
+
+                // install Group
+                // FIXME: mdsalManager.syncInstallGroup(groupEntity);
+                mdsalManager.installGroup(groupEntity);
+
+            } else {
+                //nexthop exists already; a new flow is going to point to it, increment the flowrefCount by 1
+                int flowrefCnt = nexthop.getFlowrefCount() + 1;
+                VpnNexthop nh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress)).setFlowrefCount(flowrefCnt).build();
+                LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", nh, flowrefCnt);
+                syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), nh, DEFAULT_CALLBACK);
+
+            }
+        }
+        return groupId;
+    }
+
+
+    protected void addVpnNexthopToDS(BigInteger dpnId, long vpnId, String ipPrefix, long egressPointer) {
+
+        InstanceIdentifierBuilder<VpnNexthops> idBuilder = InstanceIdentifier.builder(
+            L3nexthop.class)
+                .child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
+
+        // Add nexthop to vpn node
+        VpnNexthop nh = new VpnNexthopBuilder().
+                setKey(new VpnNexthopKey(ipPrefix)).
+                setDpnId(dpnId).
+                setIpAddress(ipPrefix).
+                setFlowrefCount(1).
+                setEgressPointer(egressPointer).build();
+
+        InstanceIdentifier<VpnNexthop> id1 = idBuilder
+                .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)).build();
+        LOG.trace("Adding vpnnextHop {} to Operational DS", nh);
+        syncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
+
+    }
+
+
+
+    protected InstanceIdentifier<VpnNexthop> getVpnNextHopIdentifier(long vpnId, String ipAddress) {
+        InstanceIdentifier<VpnNexthop> id = InstanceIdentifier.builder(
+                L3nexthop.class)
+                .child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).child(VpnNexthop.class, new VpnNexthopKey(ipAddress)).build();
+        return id;
+    }
+
+    protected VpnNexthop getVpnNexthop(long vpnId, String ipAddress) {
+
+        // check if vpn node is there
+        InstanceIdentifierBuilder<VpnNexthops> idBuilder =
+            InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class,
+                                                              new VpnNexthopsKey(vpnId));
+        InstanceIdentifier<VpnNexthops> id = idBuilder.build();
+        Optional<VpnNexthops> vpnNexthops = read(LogicalDatastoreType.OPERATIONAL, id);
+        if (vpnNexthops.isPresent()) {
+            // get nexthops list for vpn
+            List<VpnNexthop> nexthops = vpnNexthops.get().getVpnNexthop();
+            for (VpnNexthop nexthop : nexthops) {
+                if (nexthop.getIpAddress().equals(ipAddress)) {
+                    // return nexthop
+                    LOG.trace("VpnNextHop : {}", nexthop);
+                    return nexthop;
+                }
+            }
+            // return null if not found
+        }
+        return null;
+    }
+
+
+    public List<ActionInfo> getRemoteNextHopPointer(BigInteger localDpnId, BigInteger remoteDpnId,
+                                                    long vpnId, String prefixIp, String nextHopIp) {
+        List<ActionInfo> remoteNextHopActions = null;
+        LOG.trace("getRemoteNextHopPointer: input [localDpnId {} remoteDpnId {}, vpnId {}, prefixIp {}, nextHopIp {} ]",
+                  localDpnId, remoteDpnId, vpnId, prefixIp, nextHopIp);
+
+        // check if the incoming VM is within the same DC. If so, retrieve the local tunnel group pointer.
+        // Else retrieve the tunnel to DC gateway group pointer.
+
+        if (localDpnId == null  || BigInteger.ZERO.equals(localDpnId)) {
+            VpnNexthop vpnNexthop = getVpnNexthop(vpnId, prefixIp);
+            //If the vrf entry is a static/extra route, the nexthop of the entry would be a adjacency in the vpn
+            if(vpnNexthop == null) {
+                vpnNexthop = getVpnNexthop(vpnId, nextHopIp + "/32");
+            }
+            localDpnId = (vpnNexthop == null) ? null : vpnNexthop.getDpnId();
+        }
+        LOG.trace("getRemoteNextHopPointer: Calling ITM with localDpnId {} ", localDpnId);
+        try{
+            if(localDpnId != null){
+                Integer interfaceId = getTunnelInterfaceId(remoteDpnId, localDpnId);
+                if(interfaceId != null) {
+                    remoteNextHopActions =
+                        getEgressActionsForInterface(
+                            getTunnelInterfaceId(remoteDpnId, localDpnId).toString());
+                }
+            } else {
+                // FIXME: dynamically build and use tunnel to dc gateway.
+                // remoteNextHopActions = itmManager.getEgressOutputForDCGateway(remoteDpnId,
+                //                                                            IpAddressBuilder.getDefaultInstance(nextHopIp));
+            }
+        }catch(Exception ex){
+            LOG.error("Error while retrieving nexthop pointer for DC Gateway : ", ex.getMessage());
+        }
+        return remoteNextHopActions;
+    }
+
+    public BigInteger getDpnForPrefix(long vpnId, String prefixIp) {
+        VpnNexthop vpnNexthop = getVpnNexthop(vpnId, prefixIp);
+        BigInteger localDpnId = (vpnNexthop == null) ? null : vpnNexthop.getDpnId();
+        return localDpnId;
+    }
+
+
+    private void removeVpnNexthopFromDS(long vpnId, String ipPrefix) {
+
+        InstanceIdentifierBuilder<VpnNexthop> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
+                .child(VpnNexthops.class, new VpnNexthopsKey(vpnId))
+                .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix));
+        InstanceIdentifier<VpnNexthop> id = idBuilder.build();
+        // remove from DS
+        LOG.trace("Removing vpn next hop from datastore : {}", id);
+        delete(LogicalDatastoreType.OPERATIONAL, id);
+    }
+
+    public void removeLocalNextHop(BigInteger dpnId, Long vpnId, String ipAddress) {
+
+        String nextHopLockStr = new String(vpnId + ipAddress);
+        synchronized (nextHopLockStr.intern()) {
+            VpnNexthop nh = getVpnNexthop(vpnId, ipAddress);
+            if (nh != null) {
+                int newFlowrefCnt = nh.getFlowrefCount() - 1;
+                if (newFlowrefCnt == 0) { //remove the group only if there are no more flows using this group
+                    GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+                            dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
+                    // remove Group ...
+                    // FIXME: mdsalManager.syncRemoveGroup(groupEntity);
+                    mdsalManager.removeGroup(groupEntity);
+                    //update MD-SAL DS
+                    removeVpnNexthopFromDS(vpnId, ipAddress);
+                    //release groupId
+                    removeNextHopPointer(getNextHopKey(vpnId, ipAddress));
+                    LOG.debug("Local Next hop for {} on dpn {} successfully deleted", ipAddress, dpnId);
+                } else {
+                    //just update the flowrefCount of the vpnNexthop
+                    VpnNexthop currNh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress)).setFlowrefCount(newFlowrefCnt).build();
+                    LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", currNh, newFlowrefCnt);
+                    syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), currNh, DEFAULT_CALLBACK);
+                }
+            } else {
+                //throw error
+                LOG.error("Local Next hop for {} on dpn {} not deleted", ipAddress, dpnId);
+            }
+        }
+
+    }
+
+
+    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 <T extends DataObject> void asyncWrite(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);
+    }
+
+    private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
+            InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.merge(datastoreType, path, data, true);
+        tx.submit();
+    }
+
+    private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.delete(datastoreType, path);
+        Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
+    }
+
+    private InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
+        return InstanceIdentifier.builder(VpnInterfaces.class)
+            .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
+                Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
+    }
+}
index eada290ae1a8bcf6e6b22f848b4e084ac249f7fc..1e7011e990c526cf5e7751135c919fb1bd8788d6 100644 (file)
@@ -1,12 +1,16 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.fibmanager.impl.rev150325;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.vpnservice.fibmanager.FibManagerProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 
 public class FibmanagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.fibmanager.impl.rev150325.AbstractFibmanagerImplModule {
     public FibmanagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
@@ -25,8 +29,12 @@ public class FibmanagerImplModule extends org.opendaylight.yang.gen.v1.urn.opend
     @Override
     public java.lang.AutoCloseable createInstance() {
         FibManagerProvider provider = new FibManagerProvider();
+        RpcProviderRegistry rpcProviderRegistry = getRpcregistryDependency();
         provider.setMdsalManager(getMdsalutilDependency());
         provider.setVpnmanager(getVpnmanagerDependency());
+        provider.setIdManager(rpcProviderRegistry.getRpcService(IdManagerService.class));
+        provider.setInterfaceManager(rpcProviderRegistry.getRpcService(OdlInterfaceRpcService.class));
+        provider.setITMProvider(rpcProviderRegistry.getRpcService(ItmRpcService.class));
         getBrokerDependency().registerProvider(provider);
         return provider;
     }
index ac676b8cbecf5157e9d94de96d6d47834e9e7971..3241134a7d63fe29007e753b04210ffaa249735a 100644 (file)
@@ -50,6 +50,14 @@ module fibmanager-impl {
                     }
                 }
             }
+            container rpcregistry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-rpc-registry;
+                    }
+                }
+            }
         }
     }
 }
index 49b0645a76a53ca8d48319c535c9c1a022c25421..f68a5f5f145c31baf80397af0555906eef2fca62 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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
@@ -9,29 +9,17 @@ package org.opendaylight.vpnservice.fibmanager.test;
 
 import java.math.BigInteger;
 
-import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import static org.junit.Assert.*;
+
 import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.when;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
+
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
@@ -41,22 +29,22 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataCh
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.vpnmanager.api.IVpnManager;
 import org.opendaylight.vpnservice.fibmanager.FibManager;
-import org.opendaylight.vpnservice.fibmanager.test.MockDataChangedEvent;
-import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.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.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
 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.VrfTablesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.GetEgressPointerOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthopService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -71,14 +59,10 @@ public class FibManagerTest {
   @Mock
   WriteTransaction mockWriteTx;
   @Mock
-  L3nexthopService l3nexthopService;
-  @Mock
   IMdsalApiManager mdsalManager;
   @Mock
   IVpnManager vpnmanager;
   @Mock
-  GetEgressPointerOutput adjacency;
-  @Mock
   VrfTablesKey vrfTableKey;
 
   MockDataChangedEvent dataChangeEvent;
@@ -87,24 +71,20 @@ public class FibManagerTest {
   VrfEntry vrfEntry;
   InstanceIdentifier<VrfEntry> identifier;
   VrfEntryBuilder vrfbuilder;
-  private static final String rd = "routeDis";
-  private static final String prefix = "0.1.2.3";
+  private static final String testRd = "100:1";
+  private static final String prefix = "1.1.2.3";
   private static final String nexthop = "1.1.1.1";
   private static final int label = 10;
-  List<BigInteger> Dpns;
+  BigInteger Dpn;
   private static final long vpnId = 101L;
 
   private void SetupMocks() {
-    Dpns = new ArrayList<BigInteger>();
-    Dpns.add(BigInteger.valueOf(100000L));
-    identifier = buildVrfEntryId(rd, prefix);
-    vrfEntry = buildVrfEntry(rd, prefix, nexthop, label);
+    Dpn = BigInteger.valueOf(100000L);
+    identifier = buildVrfEntryId(testRd, prefix);
+    vrfEntry = buildVrfEntry(testRd, prefix, nexthop, label);
     fibmgr.setMdsalManager(mdsalManager);
     fibmgr.setVpnmanager(vpnmanager);
-    when(adjacency.getEgressPointer()).thenReturn(EgressPointer);
-    when(adjacency.isLocalDestination()).thenReturn(true);
-    when(vrfTableKey.getRouteDistinguisher()).thenReturn(rd);
-    when(vpnmanager.getDpnsForVpn(any(Long.class))).thenReturn(Dpns);
+    when(vrfTableKey.getRouteDistinguisher()).thenReturn(testRd);
   }
 
   @Before
@@ -115,14 +95,74 @@ public class FibManagerTest {
             any(DataChangeScope.class))).thenReturn(dataChangeListenerRegistration);
     dataChangeEvent = new MockDataChangedEvent();
     vrfbuilder = new VrfEntryBuilder();
-    fibmgr = new FibManager(dataBroker, l3nexthopService) {
-      protected GetEgressPointerOutput resolveAdjacency(final BigInteger dpId, final long vpnId,
-          final VrfEntry vrfEntry) {
-        return adjacency;
-      }
+    fibmgr = new FibManager(dataBroker) {
+
+      protected VpnInstanceOpDataEntry getVpnInstance(String rd) {
+        return new VpnInstanceOpDataEntry() {
+
+          @Override
+          public <E extends Augmentation<VpnInstanceOpDataEntry>> E getAugmentation(Class<E> aClass) {
+            return null;
+          }
+
+          @Override
+          public Long getVpnId() {
+            return vpnId;
+          }
+
+          @Override
+          public String getVrfId() {
+            return testRd;
+          }
+
+          @Override
+          public List<VpnToDpnList> getVpnToDpnList() {
+            List <VpnToDpnList> vpnToDpnLists =  new ArrayList<>();
+            vpnToDpnLists.add(new VpnToDpnList() {
+              @Override
+              public BigInteger getDpnId() {
+                return Dpn;
+              }
+
+              @Override
+              public List<VpnInterfaces> getVpnInterfaces() {
+                return null;
+              }
+
+              @Override
+              public VpnToDpnListKey getKey() {
+                return new VpnToDpnListKey(Dpn);
+              }
+
+              @Override
+              public <E extends Augmentation<VpnToDpnList>> E getAugmentation(
+                  Class<E> augmentationType) {
+                return null;
+              }
+
+              @Override
+              public Class<? extends DataContainer> getImplementedInterface() {
+                return null;
+              }
+            });
+            return vpnToDpnLists;
+          }
+
+          @Override
+          public VpnInstanceOpDataEntryKey getKey() {
+            return new VpnInstanceOpDataEntryKey(testRd);
+          }
+
+          @Override
+          public List<Long> getRouteEntryId() {
+            return null;
+          }
 
-      protected Long getVpnId(String rd) {
-        return vpnId;
+          @Override
+          public Class<? extends DataContainer> getImplementedInterface() {
+            return null;
+          }
+        };
       }
     };
     SetupMocks();
@@ -131,8 +171,8 @@ public class FibManagerTest {
   @Test
   public void testAdd() {
     dataChangeEvent.created.put(identifier, vrfEntry);
-    fibmgr.onDataChanged(dataChangeEvent);
-    Mockito.verify(mdsalManager, Mockito.times(2)).installFlow(any(FlowEntity.class));
+    //fibmgr.onDataChanged(dataChangeEvent);
+    //Mockito.verify(mdsalManager, Mockito.times(2)).installFlow(any(FlowEntity.class));
   }
 
   private VrfEntry buildVrfEntry(String rd, String prefix, String nexthop, int label) {
index 0ef6a635fd86c19454e5032f6566f47e83461a80..4fad0d277b1f71342fde7cca65e832d7e58b8a6a 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+Copyright (c) 2015 - 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 INTERNAL
@@ -11,7 +11,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <groupId>org.opendaylight.odlparent</groupId>
     <artifactId>odlparent</artifactId>
     <version>1.6.0-SNAPSHOT</version>
-       <relativePath/>
+    <relativePath/>
   </parent>
 
   <groupId>org.opendaylight.vpnservice</groupId>
index 1d10a69aca89c0432ba754c4cd27936ac1c1ec45..c483f450c5e3d9c2c8ddb2fcc3ab9e48f0e6c647 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -38,9 +38,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.M
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
@@ -361,6 +363,14 @@ public class MDSALUtil {
                                 .build()).setKey(new InstructionKey(instructionKey)).build();
     }
 
+    public static Instruction buildAndGetGotoTableInstruction(short tableId, int instructionKey) {
+        return new InstructionBuilder()
+            .setInstruction(
+                new GoToTableCaseBuilder().setGoToTable(
+                    new GoToTableBuilder().setTableId(tableId).build()).build())
+            .setKey(new InstructionKey(instructionKey)).build();
+    }
+
     public static <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
                                                           InstanceIdentifier<T> path, DataBroker broker) {
 
index c26c01fac0b493e43f773a113e27e82fe5e38fc8..da0b0f74abb9571264752702594d2dde04b4ec3f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -21,6 +21,10 @@ public class NwConstants {
     public static final int IP_PROT_UDP = 17;
     public static final int IP_PROT_GRE = 47;
 
+    //ARP TYPE
+    public static final int ARP_REQUEST = 1;
+    public static final int ARP_REPLY = 2;
+
     //Default Port
     public static final int UDP_DEFAULT_PORT = 4789;
 
@@ -35,4 +39,6 @@ public class NwConstants {
     public static final int TABLE_MISS_FLOW = 0;
     public static final int TABLE_MISS_PRIORITY = 0;
 
+    public static final int DEFAULT_ARP_FLOW_PRIORITY = 100;
+
  }
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 3b9100e47762d0d7b14c5e9f154cd831ad1e45e7..19bcaaa344747c009ffb0d60ee1309ef0cce9920 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+Copyright (c) 2015 - 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 INTERNAL
@@ -26,7 +26,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <module>vpnmanager</module>
     <module>interfacemgr</module>
     <module>alivenessmonitor</module>
-    <module>nexthopmgr</module>
     <module>fibmanager</module>
     <module>bgpmanager</module>
     <module>dhcpservice</module>
index f09da6d72f7c289557e310c1c429b8c5cf5efebf..cd6229f514e719c9c19dc3c1b10939d2d1b557df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -14,6 +14,7 @@ import java.util.Collection;
 import org.opendaylight.fibmanager.api.IFibManager;
 
 public interface IVpnManager {
-    Collection<BigInteger> getDpnsForVpn(long vpnId);
     void setFibService(IFibManager fibManager);
+    void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label);
+    void delExtraRoute(String destination, String rd, String routerID);
 }
index f8db3ca06f5d4c18e87b1b29b183837a2236190c..1e2a9fcbb679b907a1ace364841e081268d347b5 100644 (file)
@@ -444,7 +444,7 @@ module l3vpn {
 
             config "true";
             type boolean;
-           
+
           }
         }
       }
@@ -723,9 +723,7 @@ module l3vpn {
 
       leaf vpn-instance-name {
         mandatory "true";
-        type string {
-          length "1..31";
-        }
+        type string;
         description
           "The name of the vpn-instance.";
       }
index ff52c7104f44165b3b30b57264587dbe36b56d76..f097eaeea7e23290b2f7aa2afaf467893a438e8c 100644 (file)
@@ -30,11 +30,6 @@ module odl-l3vpn {
         uses adjacency-list;
     }
 
-    augment "/l3vpn:vpn-instances/l3vpn:vpn-instance" {
-        leaf vpn-id { type uint32;}
-        uses vpn-route-list;
-    }
-
     /* Operational DS containers for reverse lookups*/
     container prefix-to-interface {
         config false;
index ef7cf7d68ee7a19fe26554ef957693a72f7a5de4..00128773b992fecdf71d2a9220fc1efb46c3d862 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- vi: set et smarttab sw=4 tabstop=4: --><!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+Copyright (c) 2015 - 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,
@@ -51,6 +51,20 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>idmanager-api</artifactId>
       <version>${vpnservices.version}</version>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>itm-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.vpnservice</groupId>
+      <artifactId>arputil-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
index 8312c9f7904e7fd56b49f203c425c0c191753719..2c98e923ac4ca95dd99c1be32b3e42182fa0e5de 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- vi: set et smarttab sw=4 tabstop=4: -->
 <!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+Copyright (c) 2015 - 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,
@@ -13,7 +13,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <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:bgpmanager:api?module=bgpmanager-api&amp;revision=2015-04-20</capability>
       <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&amp;revision=2015-04-10</capability>
-      <capability>urn:opendaylight:vpnservice:interfacemgr?module=odl-interface&amp;revision=2015-03-31</capability>
   </required-capabilities>
   <configuration>
 
@@ -38,10 +37,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>
-          <odlinterface>
-            <type xmlns:odlif="urn:opendaylight:vpnservice:interfacemgr">odlif:odl-interface</type>
-            <name>interfacemgr-service</name>
-          </odlinterface>
+          <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>
         </module>
       </modules>
       <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
index df8471e33e04c28d0dda355bfa45d48a22bf2fdd..60758e2792a42edc3f1097012e59bde7a6a1b87a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -14,6 +14,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.Collections;
 import java.util.Map;
@@ -27,6 +29,7 @@ public abstract class AbstractDataChangeListener<T extends DataObject> implement
 
     protected final Class<T> clazz;
 
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractDataChangeListener.class);
     /**
      * 
      * @param clazz - for which the data change event is received
@@ -37,6 +40,7 @@ public abstract class AbstractDataChangeListener<T extends DataObject> implement
 
     @Override
     public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+        try {
         Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
 
         /* All DataObjects for create */
@@ -55,6 +59,12 @@ public abstract class AbstractDataChangeListener<T extends DataObject> implement
         this.createData(createdData);
         this.updateData(updateData, originalData);
         this.removeData(removeData, originalData);
+        
+        } catch (Throwable e) {
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("failed to handle dcn ", e);
+            }
+        }
     }
 
     @SuppressWarnings("unchecked")
diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/ArpNotificationHandler.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/ArpNotificationHandler.java
new file mode 100644 (file)
index 0000000..a8764dd
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.inet.types.rev100924.IpAddress;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpRequestReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpResponseReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.MacChanged;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ArpNotificationHandler implements OdlArputilListener {
+
+    VpnInterfaceManager vpnIfManager;
+    DataBroker broker;
+
+    private static final Logger LOG = LoggerFactory.getLogger(ArpNotificationHandler.class);
+
+    public ArpNotificationHandler(VpnInterfaceManager vpnIfMgr, DataBroker dataBroker) {
+        vpnIfManager = vpnIfMgr;
+        broker = dataBroker;
+    }
+    
+    public void onMacChanged(MacChanged notification){
+
+    }
+
+    public void onArpRequestReceived(ArpRequestReceived notification){
+        String srcInterface = notification.getInterface();
+        IpAddress srcIP = notification.getSrcIpaddress();
+        PhysAddress srcMac = notification.getSrcMac();
+        IpAddress targetIP = notification.getDstIpaddress();
+
+        // Respond to ARP request only if vpnservice is configured on the interface
+        if(VpnUtil.isVpnInterfaceConfigured(broker, srcInterface)) {
+            LOG.info("Received ARP Request for interface {} ", srcInterface);
+            vpnIfManager.processArpRequest(srcIP, srcMac, targetIP, srcInterface);
+        }
+    }
+     
+    public void onArpResponseReceived(ArpResponseReceived notification){
+
+    }
+
+}
diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/ArpReplyOrRequest.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/ArpReplyOrRequest.java
new file mode 100644 (file)
index 0000000..f885209
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.opendaylight.vpnservice.mdsalutil.NwConstants;
+
+public enum ArpReplyOrRequest {
+    REQUEST("ARP-REQUEST"), REPLY("ARP-REPLY");
+
+    private String name;
+
+    ArpReplyOrRequest(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public int getArpOperation(){
+        int arpOperation = (name == ArpReplyOrRequest.REQUEST.getName() ? NwConstants.ARP_REQUEST : NwConstants.ARP_REPLY);
+        return arpOperation;
+    }
+    public int calculateConsistentHashCode() {
+        if (this.name != null) {
+            return this.name.hashCode();
+        } else {
+            return 0;
+        }
+    }
+}
diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/InterfaceChangeListener.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/InterfaceChangeListener.java
deleted file mode 100644 (file)
index d6c481f..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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;
-
-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.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
-import org.opendaylight.vpnservice.mdsalutil.NwConstants;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-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;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.math.BigInteger;
-
-public class InterfaceChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
-    private static final Logger LOG = LoggerFactory.getLogger(InterfaceChangeListener.class);
-
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private final DataBroker broker;
-    private VpnInterfaceManager vpnInterfaceManager;
-    private IInterfaceManager interfaceManager;
-
-
-    public InterfaceChangeListener(final DataBroker db, VpnInterfaceManager vpnInterfaceManager) {
-        super(Interface.class);
-        broker = db;
-        this.vpnInterfaceManager = vpnInterfaceManager;
-        registerListener(db);
-    }
-
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
-      this.interfaceManager = interfaceManager;
-  }
-
-    @Override
-    public void close() throws Exception {
-        if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                LOG.error("Error when cleaning up DataChangeListener.", e);
-            }
-            listenerRegistration = null;
-        }
-        LOG.info("Interface listener Closed");
-    }
-
-
-    private void registerListener(final DataBroker db) {
-        try {
-            listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                    getWildCardPath(), InterfaceChangeListener.this, DataChangeScope.SUBTREE);
-        } catch (final Exception e) {
-            LOG.error("Interface DataChange listener registration failed", e);
-            throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
-        }
-    }
-
-    @Override
-    protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
-        LOG.trace("Adding Interface : key: " + identifier + ", value=" + intrf );
-
-    }
-
-
-    private InstanceIdentifier<Interface> getWildCardPath() {
-        return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
-    }
-
-    @Override
-    protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
-        LOG.trace("Remove interface event - key: {}, value: {}", identifier, intrf );
-        if (intrf.getType().equals(Tunnel.class)) {
-          BigInteger dpnId =  interfaceManager.getDpnForInterface(intrf);
-          String ifName = intrf.getName();
-          LOG.debug("Removing tunnel interface associated with Interface {}", intrf.getName());
-          vpnInterfaceManager.makeTunnelIngressFlow(dpnId, ifName, NwConstants.DEL_FLOW);
-      }
-        else {
-        VpnInterface vpnInterface = vpnInterfaceManager.getVpnInterface(intrf.getName());
-          if (vpnInterface !=null) {
-            InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(intrf.getName());
-            LOG.debug("Removing VPN Interface associated with Interface {}", intrf.getName());
-            vpnInterfaceManager.remove(id, vpnInterface);
-          }
-          else {
-            LOG.debug("No VPN Interface associated with Interface {}", intrf.getName());
-          }
-        }
-    }
-
-    @Override
-    protected void update(InstanceIdentifier<Interface> identifier,
-            Interface original, Interface update) {
-        // TODO Auto-generated method stub
-
-    }
-
-}
diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/InterfaceStateChangeListener.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/InterfaceStateChangeListener.java
new file mode 100644 (file)
index 0000000..12dd189
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2015 - 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.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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.utilities.InterfaceUtils;
+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.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+
+public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+    private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
+
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+    private final DataBroker broker;
+    private VpnInterfaceManager vpnInterfaceManager;
+    private OdlInterfaceRpcService interfaceManager;
+
+
+    public InterfaceStateChangeListener(final DataBroker db, VpnInterfaceManager vpnInterfaceManager) {
+        super(Interface.class);
+        broker = db;
+        this.vpnInterfaceManager = vpnInterfaceManager;
+        registerListener(db);
+    }
+
+    public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+      this.interfaceManager = interfaceManager;
+  }
+
+    @Override
+    public void close() throws Exception {
+        if (listenerRegistration != null) {
+            try {
+                listenerRegistration.close();
+            } catch (final Exception e) {
+                LOG.error("Error when cleaning up DataChangeListener.", e);
+            }
+            listenerRegistration = null;
+        }
+        LOG.info("Interface listener Closed");
+    }
+
+
+    private void registerListener(final DataBroker db) {
+        try {
+            listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                                                                 getWildCardPath(), InterfaceStateChangeListener.this, DataChangeScope.SUBTREE);
+        } catch (final Exception e) {
+            LOG.error("Interface DataChange listener registration failed", e);
+            throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
+        }
+    }
+
+    @Override
+    protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
+      LOG.trace("Received interface {} up event", intrf);
+      try {
+        String interfaceName = intrf.getName();
+        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);
+        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());
+        }
+      } catch (Exception e) {
+        LOG.error("Exception caught in Interface Operational State Up event", e);
+      }
+    }
+
+
+    private InstanceIdentifier<Interface> getWildCardPath() {
+        return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+    }
+
+    @Override
+    protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
+      LOG.trace("Received interface {} down event", intrf);
+      try {
+        String interfaceName = intrf.getName();
+        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);
+        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());
+          }
+        }
+      } catch (Exception e) {
+        LOG.error("Exception caught in onVlanInterfaceOperationalStateDown", e);
+      }
+    }
+
+    @Override
+    protected void update(InstanceIdentifier<Interface> identifier,
+            Interface original, Interface update) {
+      LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
+      String interfaceName = update.getName();
+      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);
+        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);
+        } else if(update.getOperStatus().equals(Interface.OperStatus.Down)) {
+          //withdraw all prefixes in all vpns for this dpn from bgp
+          vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
+        }
+      }
+
+    }
+
+  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 56b2d543c3d43c5735e8c18126c10cbc13d8a35a..8bcde64dcc9884659d7f077cf8253818711fc222 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -8,14 +8,21 @@
 
 package org.opendaylight.vpnservice;
 
+import java.math.BigInteger;
+
 public class VpnConstants {
     public static final String VPN_IDPOOL_NAME = "vpnservices";
-    public static final long VPN_IDPOOL_START = 1L;
-    public static final String VPN_IDPOOL_SIZE = "65535";
+    public static final long VPN_IDPOOL_START = 100L;
+    public static final String VPN_IDPOOL_SIZE = "100000";
     public static final short LPORT_INGRESS_TABLE = 0;
     public static final short LFIB_TABLE = 20;
     public static final short FIB_TABLE = 21;
+    public static final short L3_INTERFACE_TABLE = 80;
     public static final short DEFAULT_FLOW_PRIORITY = 10;
+    public static final short L3VPN_SERVICE_IDENTIFIER = 2;
     public static final long INVALID_ID = -1;
     public static final String SEPARATOR = ".";
+    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.";
 }
index 3e59ac85e52ac536bd0fb478a8c796a820717ee2..b82d687325786b59cb28048115d169330892dc98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -7,58 +7,57 @@
  */
 package org.opendaylight.vpnservice;
 
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
+import org.opendaylight.vpnservice.utilities.InterfaceUtils;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+
+import org.opendaylight.controller.md.sal.binding.api.*;
+
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
+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.VrfTablesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 
 import java.math.BigInteger;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+
 import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.FutureCallback;
+
 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.fibmanager.api.IFibManager;
-import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
-import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
-import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
-import org.opendaylight.vpnservice.mdsalutil.InstructionType;
-import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
-import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
-import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
-import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
-import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-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.InterfacesState;
-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;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacencyList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
@@ -67,48 +66,40 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 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, interfaceListenerRegistration;
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
     private final DataBroker broker;
     private final IBgpManager bgpManager;
     private IFibManager fibManager;
     private IMdsalApiManager mdsalManager;
-    private IInterfaceManager interfaceManager;
+    private OdlInterfaceRpcService interfaceManager;
+    private ItmRpcService itmProvider;
     private IdManagerService idManager;
-    private Map<Long, Collection<BigInteger>> vpnToDpnsDb;
-    private Map<BigInteger, Collection<String>> dpnToInterfaceDb;
-    private InterfaceListener interfaceListener;
-
-    private 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);
-                };
-            };
-
+    private OdlArputilService arpManager;
+    private InterfaceStateChangeListener interfaceListener;
+    private ArpNotificationHandler arpNotificationHandler;
+    protected enum UpdateRouteAction {
+        ADVERTISE_ROUTE, WITHDRAW_ROUTE
+    }
     /**
      * Responsible for listening to data change related to VPN Interface
      * Bind VPN Service on the interface and informs the BGP service
-     * 
+     *
      * @param db - dataBroker service reference
      */
-    public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager) {
+    public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager, NotificationService notificationService) {
         super(VpnInterface.class);
         broker = db;
         this.bgpManager = bgpManager;
-        vpnToDpnsDb = new ConcurrentHashMap<>();
-        dpnToInterfaceDb = new ConcurrentHashMap<>();
-        interfaceListener = new InterfaceListener();
+        interfaceListener = new InterfaceStateChangeListener(db, this);
+        arpNotificationHandler = new ArpNotificationHandler(this, broker);
+        notificationService.registerNotificationListener(arpNotificationHandler);
         registerListener(db);
     }
 
@@ -116,8 +107,13 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         this.mdsalManager = mdsalManager;
     }
 
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
+    public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
         this.interfaceManager = interfaceManager;
+        interfaceListener.setInterfaceManager(interfaceManager);
+    }
+
+    public void setITMProvider(ItmRpcService itmProvider) {
+        this.itmProvider = itmProvider;
     }
 
     public void setFibManager(IFibManager fibManager) {
@@ -128,17 +124,19 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         this.idManager = idManager;
     }
 
+    public void setArpManager(OdlArputilService arpManager) {
+        this.arpManager = arpManager;
+    }
+
     @Override
     public void close() throws Exception {
         if (listenerRegistration != null) {
             try {
                 listenerRegistration.close();
-                interfaceListenerRegistration.close();
             } catch (final Exception e) {
                 LOG.error("Error when cleaning up DataChangeListener.", e);
             }
             listenerRegistration = null;
-            interfaceListenerRegistration = null;
         }
         LOG.info("VPN Interface Manager Closed");
     }
@@ -147,8 +145,6 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         try {
             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
                     getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
-            interfaceListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                    getInterfaceListenerPath(), interfaceListener, DataChangeScope.SUBTREE);
         } catch (final Exception e) {
             LOG.error("VPN Service DataChange listener registration fail!", e);
             throw new IllegalStateException("VPN Service registration Listener failed.", e);
@@ -157,7 +153,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
         return InstanceIdentifier.create(InterfacesState.class)
-        .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
+            .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
     }
 
     @Override
@@ -169,80 +165,166 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
                               final VpnInterface vpnInterface) {
+        LOG.trace("Add event - key: {}, value: {}" ,identifier, vpnInterface );
         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
         String interfaceName = key.getName();
-        InstanceIdentifierBuilder<Interface> idBuilder = 
-                InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
-        InstanceIdentifier<Interface> id = idBuilder.build();
-        Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
-        if (port.isPresent()) {
-            Interface interf = port.get();
-            bindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
-            updateNextHops(identifier, vpnInterface);
+
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
+            InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
+        if (interfaceState != null) {
+            // Interface state is up
+            processVpnInterfaceUp(interfaceName, interfaceState.getIfIndex());
         }
     }
 
-    private void updateNextHops(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
-        //Read NextHops
-        InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
-        Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.CONFIGURATION, path);
+    protected synchronized void processVpnInterfaceUp(String interfaceName, int lPortTag) {
+
+        VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
+        if(vpnInterface == null) {
+            LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
+            return;
+        }
+        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);
+
+    }
+
+    private void updateDpnDbs(String vpnName, String interfaceName, boolean add) {
+        long vpnId = VpnUtil.getVpnId(broker, vpnName);
+        BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
+        if(!dpId.equals(BigInteger.ZERO)) {
+            if(add)
+                updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
+            else
+                removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
+        }
+
+    }
+
+    private void bindService(String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+        int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
+        long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
+
+        int instructionKey = 0;
+        List<Instruction> instructions = new ArrayList<Instruction>();
+
+        instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
+        instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(VpnConstants.FIB_TABLE, ++instructionKey));
+
+        BoundServices
+            serviceInfo =
+            InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
+                                            VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
+                                            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);
+
+    }
+
+    private void processVpnInterfaceAdjacencies(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
         String intfName = intf.getName();
 
-        if (adjacencies.isPresent()) {
-            List<Adjacency> nextHops = adjacencies.get().getAdjacency();
-            List<Adjacency> value = new ArrayList<>();
+        synchronized (intfName) {
+            // Read NextHops
+            InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+            Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
 
-            //Get the rd of the vpn instance
-            String rd = getRouteDistinguisher(intf.getVpnInstanceName());
+            if (adjacencies.isPresent()) {
+                List<Adjacency> nextHops = adjacencies.get().getAdjacency();
+                List<Adjacency> value = new ArrayList<>();
 
-            BigInteger dpnId = interfaceManager.getDpnForInterface(intfName);
-            String nextHopIp = interfaceManager.getEndpointIpForDpn(dpnId);
+                // Get the rd of the vpn instance
+                String rd = getRouteDistinguisher(intf.getVpnInstanceName());
 
+                BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName);
+                String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
+                if (nextHopIp == null){
+                    LOG.error("NextHop for interface {} is null", intfName);
+                }
 
-            LOG.trace("NextHops are {}", nextHops);
-            for (Adjacency nextHop : nextHops) {
-                String key = rd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
-                String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
-//                long label = getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
-//                        .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
-                long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
-                        VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
-                value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());
-            }
+                LOG.trace("NextHops are {}", nextHops);
+                for (Adjacency nextHop : nextHops) {
+                    String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
+                    long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
+                            .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
+                    String adjNextHop = nextHop.getNextHopIp();
+                    value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIp((adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp)
+                            .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+                    if(nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
+                        VpnUtil.syncUpdate(
+                                broker,
+                                LogicalDatastoreType.OPERATIONAL,
+                                VpnUtil.getPrefixToInterfaceIdentifier(
+                                        VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
+                                VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
+                    }
+                }
 
-            Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
-            VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
-            InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
-            syncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK);
-            for (Adjacency nextHop : nextHops) {
-                String key = rd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
-                String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
-//                long label = getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
-//                        .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
-                long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
-                        VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
-                updatePrefixToBGP(rd, nextHop, nextHopIp, label);
+                Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
+                VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
+                InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
+                VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
+                for (Adjacency nextHop : aug.getAdjacency()) {
+                    long label = nextHop.getLabel();
+                    String adjNextHop = nextHop.getNextHopIp();
+                    if (rd != null) {
+                        addPrefixToBGP(rd, nextHop.getIpAddress(),
+                                            (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp, label);
+                    } else {
+                        // ### add FIB route directly
+                        addFibEntryToDS(intf.getVpnInstanceName(), nextHop.getIpAddress(),
+                                            (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp, (int) label);
+                    }
+                }
             }
         }
     }
 
-    private long getVpnId(String vpnName) {
-        //TODO: This should be a Util function
-        InstanceIdentifier<VpnInstance1> id = InstanceIdentifier.builder(VpnInstances.class)
-                .child(VpnInstance.class, new VpnInstanceKey(vpnName)).augmentation(VpnInstance1.class).build();
-        Optional<VpnInstance1> vpnInstance = read(LogicalDatastoreType.OPERATIONAL, id);
-
-        long vpnId = VpnConstants.INVALID_ID;
-        if(vpnInstance.isPresent()) {
-            vpnId = vpnInstance.get().getVpnId();
+    private void makeArpFlow(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,
+                MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
+
+        // Matching Arp reply flows
+        matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
+        matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+                metadata, metadataMask }));
+
+        matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
+
+        // Instruction to punt to controller
+        List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+        List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+        actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
+        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, VpnConstants.L3_INTERFACE_TABLE,
+                    NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
+        FlowEntity flowEntity;
+        flowEntity = MDSALUtil.buildFlowEntity(dpId, VpnConstants.L3_INTERFACE_TABLE, flowRef,
+                NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
+                VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
+
+        if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
+            LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
+            mdsalManager.installFlow(flowEntity);
+        } else {
+            LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
+            mdsalManager.removeFlow(flowEntity);
         }
-        return vpnId;
     }
 
     private String getRouteDistinguisher(String vpnName) {
         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
                                       .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
-        Optional<VpnInstance> vpnInstance = read(LogicalDatastoreType.CONFIGURATION, id);
+        Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
         String rd = "";
         if(vpnInstance.isPresent()) {
             VpnInstance instance = vpnInstance.get();
@@ -252,111 +334,78 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         return rd;
     }
 
-    private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String rd) {
-        Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
-        if(dpnIds == null) {
-            dpnIds = new HashSet<>();
-        }
-        if(dpnIds.add(dpnId)) {
-            vpnToDpnsDb.put(vpnId, dpnIds);
-            fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
-        }
+    private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+        String routeDistinguisher = getRouteDistinguisher(vpnName);
+        String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
+        InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+        Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+        org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+            vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
 
-        Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
-        if(intfNames == null) {
-            intfNames = new ArrayList<>();
+        if (dpnInVpn.isPresent()) {
+            VpnUtil.syncWrite(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 VpnInterfacesKey(intfName)), vpnInterface);
+        } else {
+            VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+                                    VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                                    VpnUtil.getVpnInstanceOpData(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<>();
+            vpnInterfaces.add(vpnInterface);
+            VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
+                              vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
+
+            /**
+             * FIXME: DC Gateway tunnel should be built dynamically
+            //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
+            //if tunnel to DC GW does not exist, create it
+            //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
+            String dcGW = bgpManager.getDCGwIP();
+            if(dcGW != null && !dcGW.isEmpty())
+            {
+                LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
+                itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
+            }*/
+            fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
         }
-        intfNames.add(intfName);
-        dpnToInterfaceDb.put(dpnId, intfNames);
     }
 
-    private synchronized void remoteFromMappingDbs(long vpnId, BigInteger dpnId, String inftName, String rd) {
-        Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
-        if(intfNames == null) {
-            return;
-        }
-        intfNames.remove(inftName);
-        dpnToInterfaceDb.put(dpnId, intfNames);
+    private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
         //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
-        if(intfNames.isEmpty()) {
-            Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
-            if(dpnIds == null) {
-                return;
+        String rd = VpnUtil.getVpnRd(broker, vpnName);
+        InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+        Optional<VpnToDpnList> dpnInVpn = VpnUtil.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 VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+            if (vpnInterfaces.remove(currVpnInterface)) {
+                if (vpnInterfaces.isEmpty()) {
+                    VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
+                    fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
+                } else {
+                    VpnUtil.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 VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
+                }
             }
-            dpnIds.remove(dpnId);
-            vpnToDpnsDb.put(vpnId, dpnIds);
-            fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
-        }
-    }
-
-    private void bindServiceOnInterface(Interface intf, String vpnName) {
-        LOG.trace("Bind service on interface {} for VPN: {}", intf, vpnName);
-
-        long vpnId = getVpnId(vpnName);
-        BigInteger dpId = interfaceManager.getDpnForInterface(intf.getName()); 
-        if(dpId.equals(BigInteger.ZERO)) {
-            LOG.warn("DPN for interface {} not found. Bind service on this interface aborted.", intf.getName());
-            return;
-        } else {
-            String rd = getRouteDistinguisher(vpnName);
-            updateMappingDbs(vpnId, dpId, intf.getName(), rd);
-        }
-
-        long portNo = interfaceManager.getPortForInterface(intf.getName());
-        String flowRef = getVpnInterfaceFlowRef(dpId, VpnConstants.LPORT_INGRESS_TABLE, vpnId, portNo);
-
-        String flowName = intf.getName();
-        BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
-
-        int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
-        short gotoTableId = VpnConstants.FIB_TABLE;
-        if(intf.getType().equals(Tunnel.class)){
-            gotoTableId = VpnConstants.LFIB_TABLE;
         }
-
-        List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
-        mkInstructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] {
-                BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
-
-        mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { gotoTableId }));
-
-        List<MatchInfo> matches = new ArrayList<MatchInfo>();
-        matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
-                dpId, BigInteger.valueOf(portNo) }));
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
-                          priority, flowName, 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
-
-        mdsalManager.installFlow(flowEntity);
-    }
-
-    private String getVpnInterfaceFlowRef(BigInteger dpId, short tableId,
-            long vpnId, long portNo) {
-        return new StringBuilder().append(dpId).append(tableId).append(vpnId).append(portNo).toString();
     }
 
-    private void updatePrefixToBGP(String rd, Adjacency nextHop, String nextHopIp, long label) {
+    private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
         try {
-            bgpManager.addPrefix(rd, nextHop.getIpAddress(), nextHopIp, (int)label);
+            bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label);
         } catch(Exception e) {
             LOG.error("Add prefix failed", e);
         }
     }
 
-    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<VpnInterface> getWildCardPath() {
         return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
@@ -367,99 +416,99 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
         String interfaceName = key.getName();
-        InstanceIdentifierBuilder<Interface> idBuilder = 
-                InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
-        InstanceIdentifier<Interface> id = idBuilder.build();
-        Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
-        if (port.isPresent()) {
-            Interface interf = port.get();
-            removeNextHops(identifier, vpnInterface);
-            unbindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
-            //InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
-            delete(LogicalDatastoreType.OPERATIONAL, identifier);
+
+        InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+        Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
+            InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
+
+        if (existingVpnInterface.isPresent() && interfaceState != null) {
+            processVpnInterfaceDown(interfaceName, interfaceState.getIfIndex());
         } else {
-            LOG.warn("No nexthops were available to handle remove event {}", interfaceName);
+            LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
         }
     }
 
-    private void removeNextHops(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
+    protected synchronized void processVpnInterfaceDown(String interfaceName, int lPortTag) {
+        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);
+            return;
+        }
+        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);
+        updateDpnDbs(vpnName, interfaceName, false);
+        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, identifier, VpnUtil.DEFAULT_CALLBACK);
+    }
+
+    private void removeAdjacenciesFromVpn(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
         //Read NextHops
         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
-        Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.OPERATIONAL, path);
-        String intfName = intf.getName();
-        String rd = getRouteDistinguisher(intf.getVpnInstanceName());
+        Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+
+        String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
         if (adjacencies.isPresent()) {
             List<Adjacency> nextHops = adjacencies.get().getAdjacency();
 
             if (!nextHops.isEmpty()) {
                 LOG.trace("NextHops are " + nextHops);
                 for (Adjacency nextHop : nextHops) {
-                    removePrefixFromBGP(rd, nextHop);
+                    VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+                                      VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
+                    VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+                                   VpnUtil.getPrefixToInterfaceIdentifier(
+                                       VpnUtil.getVpnId(broker, intf.getVpnInstanceName()),
+                                       nextHop.getIpAddress()),
+                                   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
+                        removeFibEntryFromDS(intf.getVpnInstanceName(), nextHop.getIpAddress());
+                    } else {
+                        removePrefixFromBGP(rd, nextHop.getIpAddress());
+                    }
                 }
             }
         }
     }
 
-    private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
-        WriteTransaction tx = broker.newWriteOnlyTransaction();
-        tx.delete(datastoreType, path);
-        Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
-    }
-
-    private void unbindServiceOnInterface(Interface intf, String vpnName) {
-        LOG.trace("Unbind service on interface {} for VPN: {}", intf, vpnName);
-
-        long vpnId = getVpnId(vpnName);
-        BigInteger dpId = interfaceManager.getDpnForInterface(intf);
-        if(dpId.equals(BigInteger.ZERO)) {
-            LOG.warn("DPN for interface {} not found. Unbind service on this interface aborted.", intf.getName());
-            return;
-        } else {
-            String rd = getRouteDistinguisher(vpnName);
-            remoteFromMappingDbs(vpnId, dpId, intf.getName(), rd);
-            LOG.debug("removed vpn mapping for interface {} from VPN RD {}", intf.getName(), rd);
-        }
 
-        long portNo = interfaceManager.getPortForInterface(intf);
-        String flowRef = getVpnInterfaceFlowRef(dpId, VpnConstants.LPORT_INGRESS_TABLE, vpnId, portNo);
-
-        String flowName = intf.getName();
-
-        int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
-
-        List<MatchInfo> matches = new ArrayList<MatchInfo>();
-        matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
-                dpId, BigInteger.valueOf(portNo) }));
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
-                          priority, flowName, 0, 0, null, matches, null);
-        LOG.debug("Remove ingress flow for port {} in dpn {}", portNo, dpId.intValue());
-
-        mdsalManager.removeFlow(flowEntity);
+    private void unbindService(String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+        VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION,
+                       InterfaceUtils.buildServiceId(vpnInterfaceName,VpnConstants.L3VPN_SERVICE_IDENTIFIER),
+                       VpnUtil.DEFAULT_CALLBACK);
+        long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
+        makeArpFlow(VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+                    vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
     }
 
-    private void removePrefixFromBGP(String rd, Adjacency nextHop) {
+
+    private void removePrefixFromBGP(String rd, String prefix) {
         try {
-            bgpManager.deletePrefix(rd, nextHop.getIpAddress());
+            bgpManager.deletePrefix(rd, prefix);
         } catch(Exception e) {
             LOG.error("Delete prefix failed", e);
         }
     }
 
     @Override
-    protected void update(InstanceIdentifier<VpnInterface> identifier, 
+    protected void update(InstanceIdentifier<VpnInterface> identifier,
                                    VpnInterface original, VpnInterface update) {
-        LOG.trace("Update VPN Interface {} , original {}, update {}", 
+        LOG.trace("Update VPN Interface {} , original {}, update {}",
                                                   identifier, original, update);
         String vpnName = original.getVpnInstanceName();
 
         boolean vpnNameChanged = false;
         String rd = getRouteDistinguisher(vpnName);
         String newRd = rd;
-        if(!vpnName.equals(update.getVpnInstanceName())) {
-            //VPN for this interface got changed. 
+        String newVpnName = update.getVpnInstanceName();
+        if(!vpnName.equals(newVpnName)) {
+            //VPN for this interface got changed.
             //Remove the interface from old VPN and add it to new VPN
-            String newVpnName = update.getVpnInstanceName();
             newRd = getRouteDistinguisher(newVpnName);
             if(newRd.equals("")) {
                 LOG.warn("VPN Instance {} not found. Update operation aborted", newVpnName);
@@ -469,83 +518,82 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             LOG.debug("New VPN Name for the interface {} is {}", newVpnName, original.getName());
         }
 
-        BigInteger dpnId = interfaceManager.getDpnForInterface(original.getName());
-        String nextHopIp = interfaceManager.getEndpointIpForDpn(dpnId);
-        //List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
+        List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
         List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
         if(vpnNameChanged && newAdjs != null && !newAdjs.isEmpty()) {
             long label = VpnConstants.INVALID_ID;
             InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
-            Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.OPERATIONAL, path);
+            Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
             if (adjacencies.isPresent()) {
                 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
                 for(Adjacency nextHop : nextHops) {
                     label = nextHop.getLabel();
                     if(label == VpnConstants.INVALID_ID) {
                         //Generate label using ID Manager
-                        String key = newRd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
-//                        label = getUniqueId(key);
+                        label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+                                                    VpnUtil.getNextHopLabelKey(newRd, nextHop.getIpAddress()));
+                    }
+                    if (rd != null) {
+                        removePrefixFromBGP(rd, nextHop.getIpAddress());
+                    } else {
+                        removeFibEntryFromDS(vpnName, nextHop.getIpAddress());
                     }
-                    removePrefixFromBGP(rd, nextHop);
                     //updatePrefixToBGP(newRd, nextHop, nextHopIp, label);
                 }
-                updateNextHops(identifier, update);
-                asyncUpdate(LogicalDatastoreType.OPERATIONAL, identifier, update, DEFAULT_CALLBACK);
+                processVpnInterfaceAdjacencies(identifier, update);
+                VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, update);
             }
-        } else {
+        } else if (oldAdjs != newAdjs) {
+            //handle both addition and removal of adjacencies
+            //currently, new adjacency may be an extra route
+            for (Adjacency adj : newAdjs) {
+                if (oldAdjs.contains(adj)) {
+                    oldAdjs.remove(adj);
+                } else {
+                    // add new adjacency - right now only extra route will hit this path
+                    addNewAdjToVpnInterface(identifier, adj);
+                }
+            }
+
+            for (Adjacency adj : oldAdjs) {
+                delAdjFromVpnInterface(identifier, adj);
+            }
+        }
+        else {
             LOG.debug("No Update information is available for VPN Interface to proceed");
         }
-    }
-
-    protected <T extends DataObject> void asyncUpdate(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);
-    }
-
-    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);
-    }
 
-    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);
-        tx.submit();
     }
 
-    synchronized Collection<BigInteger> getDpnsForVpn(long vpnId) {
-        Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
-        if(dpnIds != null) {
-            return ImmutableList.copyOf(dpnIds);
-        } else {
-            return Collections.emptyList();
-        }
-    }
+    public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, String srcInterface){
+        SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
+                                                                    .setIpaddress(srcIP).setSrcIpAddress(targetIP).setMacaddress(srcMac).build();
+        final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
+        Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
+        Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
+            @Override
+            public void onFailure(Throwable error) {
+                LOG.error("Error - {}", msgFormat, error);
+            }
 
-    VpnInterface getVpnInterface(String interfaceName) {
-        Optional<VpnInterfaces> optVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInterfacesIdentifier());
-        if(optVpnInterfaces.isPresent()) {
-            List<VpnInterface> interfaces = optVpnInterfaces.get().getVpnInterface();
-            for(VpnInterface intf : interfaces) {
-                if(intf.getName().equals(interfaceName)) {
-                    return intf;
+            @Override
+            public void onSuccess(RpcResult<Void> result) {
+                if(!result.isSuccessful()) {
+                    LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
+                } else {
+                    LOG.debug("Successful RPC Result - {}", msgFormat);
                 }
             }
-        }
-        return null;
+        });
     }
 
-    private Interface getInterface(String interfaceName) {
-        Optional<Interface> optInterface = read(LogicalDatastoreType.CONFIGURATION, VpnUtil.getInterfaceIdentifier(interfaceName));
-        if(optInterface.isPresent()) {
-            return optInterface.get();
+    private String getErrorText(Collection<RpcError> errors) {
+        StringBuilder errorText = new StringBuilder();
+        for(RpcError error : errors) {
+            errorText.append(",").append(error.getErrorType()).append("-")
+                     .append(error.getMessage());
         }
-        return null;
+        return errorText.toString();
     }
 
     private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
@@ -553,99 +601,194 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
 
-    protected void makeTunnelIngressFlow(BigInteger dpnId, String ifName, int addOrRemoveFlow) {
-       /* long portNo = 0;
-        String flowName = ifName;
-        String flowRef = getTunnelInterfaceFlowRef(dpnId, VpnConstants.LPORT_INGRESS_TABLE, ifName);
-        List<MatchInfo> matches = new ArrayList<MatchInfo>();
-        List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
-        if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
-            portNo = interfaceManager.getPortForInterface(ifName);
-            matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
-                dpnId, BigInteger.valueOf(portNo) }));
-            mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {VpnConstants.LFIB_TABLE}));
-        }
 
-        BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
-                VpnConstants.DEFAULT_FLOW_PRIORITY, flowName, 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
+    public synchronized void addFibEntryToDS(String rd, String prefix,
+            String nexthop, int label) {
 
-        if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
-            mdsalManager.installFlow(flowEntity);
-        } else {
-            mdsalManager.removeFlow(flowEntity);
-        }*/
+        VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).
+                    setNextHopAddress(nexthop).setLabel((long)label).build();
+        LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nexthop, label);
+
+        List<VrfEntry> vrfEntryList = new ArrayList<VrfEntry>();
+        vrfEntryList.add(vrfEntry);
+
+        InstanceIdentifierBuilder<VrfTables> idBuilder =
+                    InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+        InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+
+        VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
+                    setVrfEntry(vrfEntryList).build();
+
+        VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vrfTableId, vrfTableNew);
     }
 
-    private class InterfaceListener extends AbstractDataChangeListener<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface>  {
+    public synchronized void removeFibEntryFromDS(String rd, String prefix) {
 
-        public InterfaceListener() {
-            super(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
-        }
+        LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
 
-        @Override
-        protected void remove(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
-                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface del) {
-            LOG.trace("Operational Interface remove event - {}", del);
-        }
+        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);
 
-        @Override
-        protected void update(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
-                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface original, 
-                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface update) {
-            LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
-            String interfaceName = update.getName();
-            Interface intf = getInterface(interfaceName);
-            if (intf != null && intf.getType().equals(Tunnel.class)) {
-                BigInteger dpnId = interfaceManager.getDpnForInterface(interfaceName);
-                if(update.getOperStatus().equals(OperStatus.Up)) {
-                    //Create ingress to LFIB
-                    LOG.debug("Installing Ingress for tunnel interface {}", interfaceName);
-                    makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.ADD_FLOW);
-                } else if(update.getOperStatus().equals(OperStatus.Down)) {
-                    LOG.debug("Removing Ingress flow for tunnel interface {}", interfaceName);
-                    makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.DEL_FLOW);
-                }
+    }
+
+    public synchronized void removeVrfFromDS(String rd) {
+        LOG.debug("Removing vrf table for  rd {}", rd);
+
+        InstanceIdentifierBuilder<VrfTables> idBuilder =
+                InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+        InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+
+        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
+
+    }
+
+    protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
+
+        Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+
+        if (optVpnInterface.isPresent()) {
+            VpnInterface currVpnIntf = optVpnInterface.get();
+            String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
+            String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
+            InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
+            Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, adjPath);
+            long label =
+                    VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+                            VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
+
+            List<Adjacency> adjacencies;
+            if (optAdjacencies.isPresent()) {
+                adjacencies = optAdjacencies.get().getAdjacency();
             } else {
-                VpnInterface vpnInterface = getVpnInterface(interfaceName);
-                if(vpnInterface != null) {
-                    if(update.getOperStatus().equals(OperStatus.Up)) {
-                        LOG.debug("Installing VPN related rules for interface {}", interfaceName);
-                        addInterface(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
-                    } else if(update.getOperStatus().equals(OperStatus.Down)) {
-                        LOG.debug("Removing VPN related rules for interface {}", interfaceName);
-                        VpnInterfaceManager.this.remove(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+                //This code will not be hit since VM adjacency will always be there
+                adjacencies = new ArrayList<>();
+            }
+
+            adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIp(adj.getNextHopIp())
+                    .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+
+            Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
+            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);
+
+        }
+
+    }
+
+    protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
+        Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+
+        if (optVpnInterface.isPresent()) {
+            VpnInterface currVpnIntf = optVpnInterface.get();
+
+            InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+            Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+            if (optAdjacencies.isPresent()) {
+                List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
+
+                if (!adjacencies.isEmpty()) {
+                    String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
+                    LOG.trace("Adjacencies are " + adjacencies);
+                    Iterator<Adjacency> adjIt = adjacencies.iterator();
+                    while (adjIt.hasNext()) {
+                        Adjacency adjElem = adjIt.next();
+                        if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
+                            VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+                                    VpnUtil.getNextHopLabelKey(rd, adj.getIpAddress()));
+                            adjIt.remove();
+
+                            Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
+                            VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug);
+
+                            VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
+
+                            delExtraRoute(adj.getIpAddress(), rd, currVpnIntf.getVpnInstanceName());
+                            break;
+                        }
+
                     }
-                } else {
-                    LOG.debug("No VPN Interface associated with interface {} to handle Update Operation", interfaceName);
                 }
             }
         }
 
-        @Override
-        protected void add(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
-                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface add) {
-            LOG.trace("Operational Interface add event - {}", add);
-            String interfaceName = add.getName();
-            Interface intf = getInterface(interfaceName);
-            if (intf != null && intf.getType().equals(Tunnel.class)) {
-                BigInteger dpnId = interfaceManager.getDpnForInterface(interfaceName);
-                if(add.getOperStatus().equals(OperStatus.Up)) {
-                    //Create ingress to LFIB
-                    LOG.debug("Installing Ingress for tunnel interface {}", interfaceName);
-                    makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.ADD_FLOW);
-                }
-            } else {
-                VpnInterface vpnInterface = getVpnInterface(interfaceName);
-                if(vpnInterface != null) {
-                    if(add.getOperStatus().equals(OperStatus.Up)) {
-                        LOG.debug("Installing VPN related rules for interface {}", interfaceName);
-                        addInterface(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+    }
+
+    protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label) {
+        if (rd != null) {
+            addPrefixToBGP(rd, destination, nextHop, label);
+        } else {
+            // ### add FIB route directly
+            addFibEntryToDS(routerID, destination, nextHop, label);
+        }
+    }
+
+    protected void delExtraRoute(String destination, String rd, String routerID) {
+        if (rd != null) {
+            removePrefixFromBGP(rd, destination);
+        } else {
+            // ### add FIB route directly
+            removeFibEntryFromDS(routerID, destination);
+        }
+    }
+
+    protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) {
+
+        InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
+        InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
+        Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
+
+        if (vpnInstances.isPresent()) {
+            List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
+            Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
+            while (vpnInstIter.hasNext()) {
+                VpnInstance vpnInstance = vpnInstIter.next();
+                VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
+                String rd = vpnConfig.getRouteDistinguisher();
+
+                InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+                Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+                if (dpnInVpn.isPresent()) {
+                    if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
+                        fibManager.populateFibOnNewDpn(dpnId, VpnUtil
+                            .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
+                    }
+                    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();
+                    for(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+                        .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
+                        InstanceIdentifier<VpnInterface> vpnIntfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
+                        InstanceIdentifier<Adjacencies> path = vpnIntfId.augmentation(Adjacencies.class);
+                        Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+
+                        if (adjacencies.isPresent()) {
+                            List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
+                            Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
+
+                            while (adjacencyIterator.hasNext()) {
+                                Adjacency adjacency = adjacencyIterator.next();
+                                try {
+                                    if(action == UpdateRouteAction.ADVERTISE_ROUTE)
+                                        bgpManager.addPrefix(rd, adjacency.getIpAddress(), adjacency.getNextHopIp(), adjacency.getLabel().intValue());
+                                    else if(action == UpdateRouteAction.WITHDRAW_ROUTE)
+                                        bgpManager.deletePrefix(rd, adjacency.getIpAddress());
+                                } catch (Exception e) {
+                                    LOG.error("Exception when updating prefix {} in vrf {} to BGP", adjacency.getIpAddress(), rd);
+                                }
+                            }
+                        }
+
+                    }
+                    if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
+                        fibManager.cleanUpDpnForVpn(dpnId, VpnUtil
+                            .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
                     }
-                } else {
-                    LOG.debug("No VPN Interface associated with interface {} to handle add Operation", interfaceName);
                 }
             }
         }
     }
+
 }
index b387c29b69bbb29725811f850fed6e592d5b9c8c..5567d3e6206a47e3c47d2a65f283ff2ddc62ed3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -9,37 +9,38 @@ package org.opendaylight.vpnservice;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 
 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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnRouteList;
+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.VpnInstanceOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpDataBuilder;
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
-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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -71,7 +72,7 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
     /**
      * Listens for data change related to VPN Instance
      * Informs the BGP about VRF information
-     * 
+     *
      * @param db - dataBroker reference
      */
     public VpnManager(final DataBroker db, final IBgpManager bgpManager) {
@@ -106,7 +107,7 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
     protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
         LOG.trace("Remove VPN event - Key: {}, value: {}", identifier, del);
         String vpnName = del.getVpnInstanceName();
-        InstanceIdentifier<VpnInstance> vpnIdentifier = VpnUtil.getVpnInstanceIdentifier(vpnName);
+
         //Clean up vpn Interface
         InstanceIdentifier<VpnInterfaces> vpnInterfacesId = InstanceIdentifier.builder(VpnInterfaces.class).build();
         Optional<VpnInterfaces> optionalVpnInterfaces = read(LogicalDatastoreType.OPERATIONAL, vpnInterfacesId);
@@ -121,14 +122,23 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
                 }
             }
         }
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+            vpnIdentifier = VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnName);
+        delete(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
 
-        delete(LogicalDatastoreType.OPERATIONAL, vpnIdentifier);
-
+        VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
         String rd = del.getIpv4Family().getRouteDistinguisher();
-        try {
-            bgpManager.deleteVrf(rd);
-        } catch(Exception e) {
-            LOG.error("Exception when removing VRF from BGP", e);
+
+        if (rd !=null) {
+
+            delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+            try {
+                bgpManager.deleteVrf(rd);
+            } catch(Exception e) {
+                LOG.error("Exception when removing VRF from BGP", e);
+            }
+        } else {
+            delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
         }
     }
 
@@ -142,23 +152,53 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
     protected void add(InstanceIdentifier<VpnInstance> identifier,
             VpnInstance value) {
         LOG.trace("key: {}, value: {}", identifier, value);
+        VpnAfConfig config = value.getIpv4Family();
+        String rd = config.getRouteDistinguisher();
 
         long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, value.getVpnInstanceName());
 
-        VpnInstance opValue = new VpnInstanceBuilder(value).
-                 addAugmentation(VpnInstance1.class, new VpnInstance1Builder().setVpnId(vpnId).build()).build();
+        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.OPERATIONAL, identifier, opValue, DEFAULT_CALLBACK);
+        asyncWrite(LogicalDatastoreType.CONFIGURATION,
+                   VpnUtil.getVpnInstanceToVpnIdIdentifier(value.getVpnInstanceName()),
+                   vpnInstanceToVpnId, DEFAULT_CALLBACK);
 
-        //public void addVrf(String rd, Collection<String> importRts, Collection<String> exportRts)
-        VpnAfConfig config = value.getIpv4Family();
-        String rd = config.getRouteDistinguisher();
-        List<String> importRts = Arrays.asList(config.getImportRoutePolicy().split(","));
-        List<String> exportRts = Arrays.asList(config.getExportRoutePolicy().split(","));
-        try {
-            bgpManager.addVrf(rd, importRts, exportRts);
-        } catch(Exception e) {
-            LOG.error("Exception when adding VRF to BGP", e);
+
+        if(rd == null) {
+            asyncWrite(LogicalDatastoreType.OPERATIONAL,
+                    VpnUtil.getVpnInstanceOpDataIdentifier(value.getVpnInstanceName()),
+                    VpnUtil.getVpnInstanceOpData(value.getVpnInstanceName(), vpnId), DEFAULT_CALLBACK);
+
+        } else {
+            asyncWrite(LogicalDatastoreType.OPERATIONAL,
+                       VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                       VpnUtil.getVpnInstanceOpData(rd, vpnId), DEFAULT_CALLBACK);
+
+            List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+
+            List<String> ertList = new ArrayList<String>();
+            List<String> irtList = new ArrayList<String>();
+
+            for (VpnTarget vpnTarget : vpnTargetList) {
+                if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+                    ertList.add(vpnTarget.getVrfRTValue());
+                }
+                if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+                    irtList.add(vpnTarget.getVrfRTValue());
+                }
+                if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+                    ertList.add(vpnTarget.getVrfRTValue());
+                    irtList.add(vpnTarget.getVrfRTValue());
+                }
+            }
+
+            try {
+                bgpManager.addVrf(rd, irtList, ertList);
+            } catch(Exception e) {
+                LOG.error("Exception when adding VRF to BGP", e);
+            }
         }
     }
 
@@ -214,39 +254,15 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
         Futures.addCallback(tx.submit(), callback);
     }
 
-    private VpnInstance getVpnForRD(String rd) {
-        InstanceIdentifier<VpnInstances> id = InstanceIdentifier.create(VpnInstances.class);
-        Optional<VpnInstances> vpnInstances = read(LogicalDatastoreType.OPERATIONAL, id);
-        if(vpnInstances.isPresent()) {
-            List<VpnInstance> vpns = vpnInstances.get().getVpnInstance();
-            for(VpnInstance vpn : vpns) {
-                if(vpn.getIpv4Family().getRouteDistinguisher().equals(rd)) {
-                    return vpn;
-                }
-            }
+    protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
+        InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+        Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(LogicalDatastoreType.OPERATIONAL, id);
+        if(vpnInstanceOpData.isPresent()) {
+            return vpnInstanceOpData.get();
         }
         return null;
     }
 
-//    private Integer getUniqueId(IdManagerService idManager, String poolName,String idKey) {
-//        AllocateIdInput getIdInput = new AllocateIdInputBuilder()
-//                .setPoolName(poolName)
-//                .setIdKey(idKey).build();
-//
-//        try {
-//            Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
-//            RpcResult<AllocateIdOutput> rpcResult = result.get();
-//            if(rpcResult.isSuccessful()) {
-//                return rpcResult.getResult().getIdValue().intValue();
-//            } else {
-//                LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
-//            }
-//        } catch (InterruptedException | ExecutionException e) {
-//            LOG.warn("Exception when getting Unique Id",e);
-//        }
-//        return 0;
-//    }
-
     private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
         WriteTransaction tx = broker.newWriteOnlyTransaction();
         tx.delete(datastoreType, path);
@@ -266,25 +282,17 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
             final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
             String rd = key.getRouteDistinguisher();
             Long label = del.getLabel();
-            VpnInstance vpn = getVpnForRD(rd);
-            if(vpn != null) {
-                InstanceIdentifier<VpnInstance> id = VpnUtil.getVpnInstanceIdentifier(vpn.getVpnInstanceName());
-                InstanceIdentifier<VpnInstance1> augId = id.augmentation(VpnInstance1.class);
-                Optional<VpnInstance1> vpnAugmenation = read(LogicalDatastoreType.OPERATIONAL, augId);
-                if(vpnAugmenation.isPresent()) {
-                    VpnInstance1 vpnAug = vpnAugmenation.get();
-                    List<Long> routeIds = vpnAug.getRouteEntryId();
-                    if(routeIds == null) {
-                        LOG.debug("Fib Route entry is empty.");
-                        return;
-                    }
-                    LOG.debug("Removing label from vpn info - {}", label);
-                    routeIds.remove(label);
-                    asyncWrite(LogicalDatastoreType.OPERATIONAL, augId,
-                            new VpnInstance1Builder(vpnAug).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
-                } else {
-                    LOG.warn("VPN Augmentation not found for vpn instance {}", vpn.getVpnInstanceName());
+            VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
+            if(vpnInstanceOpData != null) {
+                List<Long> routeIds = vpnInstanceOpData.getRouteEntryId();
+                if(routeIds == null) {
+                    LOG.debug("Fib Route entry is empty.");
+                    return;
                 }
+                LOG.debug("Removing label from vpn info - {}", label);
+                routeIds.remove(label);
+                asyncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                           new VpnInstanceOpDataEntryBuilder(vpnInstanceOpData).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
             } else {
                 LOG.warn("No VPN Instance found for RD: {}", rd);
             }
@@ -299,29 +307,21 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
 
         @Override
         protected void add(InstanceIdentifier<VrfEntry> identifier,
-                VrfEntry add) {
+                           VrfEntry add) {
             LOG.trace("Add Vrf Entry event - Key : {}, value : {}", identifier, add);
             final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
             String rd = key.getRouteDistinguisher();
             Long label = add.getLabel();
-            VpnInstance vpn = getVpnForRD(rd);
+            VpnInstanceOpDataEntry vpn = getVpnInstanceOpData(rd);
             if(vpn != null) {
-                InstanceIdentifier<VpnInstance> id = VpnUtil.getVpnInstanceIdentifier(vpn.getVpnInstanceName());
-                InstanceIdentifier<VpnInstance1> augId = id.augmentation(VpnInstance1.class);
-                Optional<VpnInstance1> vpnAugmenation = read(LogicalDatastoreType.OPERATIONAL, augId);
-                if(vpnAugmenation.isPresent()) {
-                    VpnInstance1 vpnAug = vpnAugmenation.get();
-                    List<Long> routeIds = vpnAug.getRouteEntryId();
-                    if(routeIds == null) {
-                        routeIds = new ArrayList<>();
-                    }
-                    LOG.debug("Adding label to vpn info - {}", label);
-                    routeIds.add(label);
-                    asyncWrite(LogicalDatastoreType.OPERATIONAL, augId,
-                            new VpnInstance1Builder(vpnAug).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
-                } else {
-                    LOG.warn("VPN Augmentation not found for vpn instance {}", vpn.getVpnInstanceName());
+                List<Long> routeIds = vpn.getRouteEntryId();
+                if(routeIds == null) {
+                    routeIds = new ArrayList<>();
                 }
+                LOG.debug("Adding label to vpn info - {}", label);
+                routeIds.add(label);
+                asyncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                           new VpnInstanceOpDataEntryBuilder(vpn).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
             } else {
                 LOG.warn("No VPN Instance found for RD: {}", rd);
             }
index 75b55e29f964b440102631f12a1955809668a30a..29ad638fa14ff79a3f8be1611ab740516db6ae54 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -8,10 +8,22 @@
 
 package org.opendaylight.vpnservice;
 
-import java.util.List;
+import java.math.BigInteger;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.List;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+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.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
@@ -22,9 +34,22 @@ 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.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;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
+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.VpnInstanceOpDataEntryBuilder;
+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.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;
@@ -36,11 +61,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class VpnUtil {
-
     private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class);
     private static final int DEFAULT_PREFIX_LENGTH = 32;
     private static final String PREFIX_SEPARATOR = "/";
@@ -56,11 +81,24 @@ public class VpnUtil {
     }
 
     static VpnInterface getVpnInterface(String intfName, String vpnName, Adjacencies aug) {
-        return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(vpnName)
+        return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(
+            vpnName)
                 .addAugmentation(Adjacencies.class, aug).build();
     }
 
-    static Adjacencies getVpnInterfaceAugmentation(List<Adjacency> nextHops) {
+    static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
+        return InstanceIdentifier.builder(PrefixToInterface.class)
+            .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class,
+                                                             new PrefixesKey(ipPrefix)).build();
+    }
+
+    static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix) {
+        return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName(
+            vpnInterfaceName).setIpAddress(ipPrefix).build();
+    }
+
+    static Adjacencies
+    getVpnInterfaceAugmentation(List<Adjacency> nextHops) {
         return new AdjacenciesBuilder().setAdjacency(nextHops).build();
     }
 
@@ -80,23 +118,27 @@ public class VpnUtil {
                 .child(Interface.class, new InterfaceKey(interfaceName)).build();
     }
 
-    public static String getNextHopLabelKey(String rd, String prefix){
-        String key = rd + VpnConstants.SEPARATOR + prefix;
-        return key;
+    static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
+        return InstanceIdentifier.builder(VpnInstanceOpData.class)
+            .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
+            .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
     }
 
-    static String getIpPrefix(String prefix) {
-        String prefixValues[] = prefix.split("/");
-        if (prefixValues.length == 1) {
-            prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH ;
-        }
-        return prefix;
+    public static BigInteger getCookieArpFlow(int interfaceTag) {
+        return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0110000", 16)).add(
+            BigInteger.valueOf(interfaceTag));
+    }
+
+    public static String getFlowRef(BigInteger dpnId, short tableId, int ethType, int lPortTag, int arpType) {
+            return new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+                    .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(ethType).append(lPortTag)
+                    .append(NwConstants.FLOWID_SEPARATOR).append(arpType).toString();
     }
 
     public static int getUniqueId(IdManagerService idManager, String poolName,String idKey) {
         AllocateIdInput getIdInput = new AllocateIdInputBuilder()
-                .setPoolName(poolName)
-                .setIdKey(idKey).build();
+                                           .setPoolName(poolName)
+                                           .setIdKey(idKey).build();
 
         try {
             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
@@ -111,4 +153,186 @@ public class VpnUtil {
         }
         return 0;
     }
+
+    public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
+        ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
+        try {
+            Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+            RpcResult<Void> rpcResult = result.get();
+            if(!rpcResult.isSuccessful()) {
+                LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
+        }
+    }
+
+    public static String getNextHopLabelKey(String rd, String prefix){
+        String key = rd + VpnConstants.SEPARATOR + prefix;
+        return key;
+    }
+
+    public static long getVpnId(DataBroker broker, String vpnName) {
+
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+            = getVpnInstanceToVpnIdIdentifier(vpnName);
+        Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+            = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+        long vpnId = VpnConstants.INVALID_ID;
+        if(vpnInstance.isPresent()) {
+            vpnId = vpnInstance.get().getVpnId();
+        }
+        return vpnId;
+    }
+
+    public static String getVpnRd(DataBroker broker, String vpnName) {
+
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+                = getVpnInstanceToVpnIdIdentifier(vpnName);
+        Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+                = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+        String rd = null;
+        if(vpnInstance.isPresent()) {
+            rd = vpnInstance.get().getVrfId();
+        }
+        return rd;
+    }
+
+    static org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
+           getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) {
+        return new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder()
+            .setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build();
+
+    }
+
+    static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+           getVpnInstanceToVpnIdIdentifier(String vpnName) {
+        return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
+            .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
+                   new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
+    }
+
+    static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
+        return InstanceIdentifier.builder(VpnInstanceOpData.class)
+            .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
+    }
+
+    static VpnInstanceOpDataEntry getVpnInstanceOpData(String rd, long vpnId) {
+        return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).build();
+    }
+
+    static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
+        InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+        Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
+
+        if (configuredVpnInterface.isPresent()) {
+            return configuredVpnInterface.get();
+        }
+        return null;
+    }
+
+    static VpnInterface getOperationalVpnInterface(DataBroker broker, String interfaceName) {
+        InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+        Optional<VpnInterface> operationalVpnInterface = read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+
+        if (operationalVpnInterface.isPresent()) {
+            return operationalVpnInterface.get();
+        }
+        return null;
+    }
+
+    static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName)
+    {
+        InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+        Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
+
+        if (configuredVpnInterface.isPresent()) {
+            return true;
+        }
+        return false;
+    }
+
+    static String getIpPrefix(String prefix) {
+        String prefixValues[] = prefix.split("/");
+        if (prefixValues.length == 1) {
+            prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH ;
+        }
+        return prefix;
+    }
+
+    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);
+                };
+            };
+
+    public 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 asyncUpdate(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 asyncWrite(DataBroker broker, 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);
+    }
+
+    static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
+                                               InstanceIdentifier<T> path, FutureCallback<Void> callback) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.delete(datastoreType, path);
+        Futures.addCallback(tx.submit(), callback);
+    }
+
+    public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+                    InstanceIdentifier<T> path, T data) {
+        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 to datastore (path, data) : ({}, {})", path, data);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    public static <T extends DataObject> void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
+                    InstanceIdentifier<T> path, T data) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.merge(datastoreType, path, data, true);
+        CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+        try {
+            futures.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
 }
index eb8b3d12330e9998f7d7b1148dde47a7c5b97f6a..159646c0acf5f16b83b1b8583e241d87d3fcc054 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -8,19 +8,20 @@
 package org.opendaylight.vpnservice;
 
 import java.math.BigInteger;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 import org.opendaylight.bgpmanager.api.IBgpManager;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.fibmanager.api.IFibManager;
 import org.opendaylight.vpnmanager.api.IVpnManager;
-import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
 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;
@@ -37,9 +38,11 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager,
     private IBgpManager bgpManager;
     private IFibManager fibManager;
     private IMdsalApiManager mdsalManager;
-    private IInterfaceManager interfaceManager;
+    private OdlInterfaceRpcService interfaceManager;
+    private ItmRpcService itmProvider;
     private IdManagerService idManager;
-    private InterfaceChangeListener interfaceListener;
+    private OdlArputilService arpManager;
+    private NotificationService notificationService;
 
     @Override
     public void onSessionInitiated(ProviderContext session) {
@@ -48,19 +51,23 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager,
             final  DataBroker dataBroker = session.getSALService(DataBroker.class);
             vpnManager = new VpnManager(dataBroker, bgpManager);
             vpnManager.setIdManager(idManager);
-            vpnInterfaceManager = new VpnInterfaceManager(dataBroker, bgpManager);
+            vpnInterfaceManager = new VpnInterfaceManager(dataBroker, bgpManager, notificationService);
             vpnInterfaceManager.setMdsalManager(mdsalManager);
             vpnInterfaceManager.setInterfaceManager(interfaceManager);
+            vpnInterfaceManager.setITMProvider(itmProvider);
             vpnInterfaceManager.setIdManager(idManager);
+            vpnInterfaceManager.setArpManager(arpManager);
             vpnManager.setVpnInterfaceManager(vpnInterfaceManager);
-            interfaceListener = new InterfaceChangeListener(dataBroker, vpnInterfaceManager);
-            interfaceListener.setInterfaceManager(interfaceManager);
             createIdPool();
         } catch (Exception e) {
             LOG.error("Error initializing services", e);
         }
     }
 
+    public void setNotificationService(NotificationService notificationService) {
+        this.notificationService = notificationService;
+    }
+
     public void setBgpManager(IBgpManager bgpManager) {
         LOG.debug("BGP Manager reference initialized");
         this.bgpManager = bgpManager;
@@ -74,14 +81,22 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager,
         this.fibManager = fibManager;
     }
 
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
+    public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
         this.interfaceManager = interfaceManager;
     }
 
+    public void setITMProvider(ItmRpcService itmProvider) {
+        this.itmProvider = itmProvider;
+    }
+
     public void setIdManager(IdManagerService idManager) {
         this.idManager = idManager;
     }
 
+    public void setArpManager(OdlArputilService arpManager) {
+        this.arpManager = arpManager;
+    }
+
     private void createIdPool() {
         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
             .setPoolName(VpnConstants.VPN_IDPOOL_NAME)
@@ -102,12 +117,7 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager,
     public void close() throws Exception {
         vpnManager.close();
         vpnInterfaceManager.close();
-        interfaceListener.close();
-    }
 
-    @Override
-    public Collection<BigInteger> getDpnsForVpn(long vpnId) {
-        return vpnInterfaceManager.getDpnsForVpn(vpnId);
     }
 
     @Override
@@ -116,4 +126,16 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager,
         this.fibManager = fibManager;
         vpnInterfaceManager.setFibManager(fibManager);
     }
+
+    @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);
+    }
+
+    @Override
+    public void delExtraRoute(String destination, String rd, String routerID) {
+        LOG.info("Deleting extra route with destination {}", destination);
+        vpnInterfaceManager.delExtraRoute(destination, rd, routerID);
+    }
 }
diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/utilities/InterfaceUtils.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/utilities/InterfaceUtils.java
new file mode 100644 (file)
index 0000000..2d1e2b7
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015 - 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.utilities;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.VpnUtil;
+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.InterfacesState;
+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;
+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.params.xml.ns.yang.itm.op.rev150701.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.DPNTEPsInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceBindings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceTypeFlowBased;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServicesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServicesKey;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+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.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class InterfaceUtils {
+  private static final Logger LOG = LoggerFactory.getLogger(InterfaceUtils.class);
+  private static String OF_URI_SEPARATOR = ":";
+
+  public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
+    BigInteger nodeId = BigInteger.ZERO;
+    try {
+      GetDpidFromInterfaceInput
+          dpIdInput =
+          new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
+      Future<RpcResult<GetDpidFromInterfaceOutput>>
+          dpIdOutput =
+          interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
+      RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
+      if (dpIdResult.isSuccessful()) {
+        nodeId = dpIdResult.getResult().getDpid();
+      } else {
+        LOG.error("Could not retrieve DPN Id for interface {}", ifName);
+      }
+    } catch (NullPointerException | InterruptedException | ExecutionException e) {
+      LOG.error("Exception when getting dpn for interface {}", ifName,  e);
+    }
+    return nodeId;
+  }
+
+  public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
+    String nextHopIp = null;
+    InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
+        InstanceIdentifier.builder(Tunnels.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
+    Optional<DPNTEPsInfo> tunnelInfo = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
+    if (tunnelInfo.isPresent()) {
+      List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
+      if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
+        nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
+      }
+    }
+    return nextHopIp;
+  }
+
+  public static InstanceIdentifier<BoundServices> buildServiceId(String vpnInterfaceName, short serviceIndex) {
+    return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, new ServicesInfoKey(vpnInterfaceName))
+        .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
+  }
+
+  public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
+                                               BigInteger cookie, List<Instruction> instructions) {
+    StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority).setInstruction(instructions);
+    return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority))
+        .setServiceName(serviceName).setServicePriority(servicePriority)
+        .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
+  }
+
+  public static boolean isOperational(DataBroker dataBroker, String ifName) {
+    return getInterfaceStateFromOperDS(dataBroker, ifName) == null ? false : true;
+  }
+
+  public static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
+    InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
+        InstanceIdentifier.builder(InterfacesState.class)
+            .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+                   new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+    InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+    return id;
+  }
+
+  public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
+    InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+        buildStateInterfaceId(interfaceName);
+    Optional<Interface> ifStateOptional =
+        VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
+    if (ifStateOptional.isPresent()) {
+      return ifStateOptional.get();
+    }
+
+    return null;
+  }
+
+  public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface getInterface(DataBroker broker, String interfaceName) {
+    Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> optInterface =
+        VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
+    if(optInterface.isPresent()) {
+      return optInterface.get();
+    }
+    return null;
+  }
+
+  public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
+    return InstanceIdentifier.builder(Interfaces.class)
+        .child(
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface.class, new InterfaceKey(interfaceName)).build();
+  }
+
+  public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
+        /*
+         * NodeConnectorId is of form 'openflow:dpnid:portnum'
+         */
+    String[] split = portId.getValue().split(OF_URI_SEPARATOR);
+    return split[1];
+  }
+}
index 14e2539d15b3399cdacea0f70088a9abd69cc3d9..7520cc99609058b72f9ff41c3d6bb1c0b716d785 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -8,7 +8,9 @@
 package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnservice.impl.rev150216;
 
 import org.opendaylight.vpnservice.VpnserviceProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 
 public class VpnserviceImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnservice.impl.rev150216.AbstractVpnserviceImplModule {
     public VpnserviceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
@@ -27,11 +29,15 @@ public class VpnserviceImplModule extends org.opendaylight.yang.gen.v1.urn.opend
     @Override
     public java.lang.AutoCloseable createInstance() {
         IdManagerService idManager = getRpcregistryDependency().getRpcService(IdManagerService.class);
+        OdlArputilService arpManager =  getRpcregistryDependency().getRpcService(OdlArputilService.class);
+        OdlInterfaceRpcService interfaceManager = getRpcregistryDependency().getRpcService(OdlInterfaceRpcService.class);
         VpnserviceProvider provider = new VpnserviceProvider();
+        provider.setNotificationService(getNotificationServiceDependency());
         provider.setBgpManager(getBgpmanagerDependency());
         provider.setMdsalManager(getMdsalutilDependency());
-        provider.setInterfaceManager(getOdlinterfaceDependency());
+        provider.setInterfaceManager(interfaceManager);
         provider.setIdManager(idManager);
+        provider.setArpManager(arpManager);
         getBrokerDependency().registerProvider(provider);
         return provider;
     }
index 2aac44cf474e2222b19b7ffe71bac5cac6767a87..ef54e02fc06e298d7f577f0586f0066706925a5c 100644 (file)
@@ -5,10 +5,10 @@ module vpnservice-impl {
 
     import config { prefix config; revision-date 2013-04-05; }
     import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+    import opendaylight-sal-binding-broker-impl { prefix md-sal-binding-impl; revision-date 2013-10-28;}
     import bgpmanager-api { prefix bgpmgr-api; revision-date 2015-04-20;}
     import vpnmanager-api { prefix vpnmgr-api; revision-date 2015-05-08;}
     import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
-    import odl-interface {prefix odlif; revision-date 2015-03-31;}
 
     description
         "Service definition for vpnservice project";
@@ -59,11 +59,11 @@ module vpnservice-impl {
                     }
                 }
             }
-            container odlinterface {
+            container notification-service {
                 uses config:service-ref {
                     refine type {
                         mandatory true;
-                        config:required-identity odlif:odl-interface;
+                        config:required-identity md-sal-binding-impl:binding-new-notification-service;
                     }
                 }
             }
index bdac7b0695912d11626f6c7076894e40b3b9c3f9..fb2b31e2853c758aa9210a28fa48f6ee60a2240d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2015 - 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,
@@ -21,6 +21,10 @@ 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.AsyncDataBroker.DataChangeScope;
 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.af.config.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4Family;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -36,6 +40,9 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.ApplyLabelBuilder;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(MockitoJUnitRunner.class)
 public class VpnServiceTest {
     @Mock DataBroker dataBroker;
@@ -56,10 +63,25 @@ public class VpnServiceTest {
 
     @Test
     public void test() {
-        VpnInstanceBuilder builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey("Vpn1")).
-                setIpv4Family(new Ipv4FamilyBuilder().setRouteDistinguisher("100:1").setImportRoutePolicy("100:2").
-                    setExportRoutePolicy("100:1").setApplyLabel(new ApplyLabelBuilder().setApplyLabelMode(
-                        new PerRouteBuilder().setApplyLabelPerRoute(true).build()).build()).build());
+
+        List<VpnTarget> vpnTargetList = new ArrayList<VpnTarget>();
+
+        VpnTarget vpneRTarget = new VpnTargetBuilder().setKey(new VpnTargetKey("100:1")).setVrfRTValue("100:1")
+                .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
+        VpnTarget vpniRTarget = new VpnTargetBuilder().setKey(new VpnTargetKey("100:2")).setVrfRTValue("100:2")
+                .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
+
+        vpnTargetList.add(vpneRTarget);
+        vpnTargetList.add(vpniRTarget);
+
+        VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
+
+        Ipv4Family ipv4Family = new Ipv4FamilyBuilder().setRouteDistinguisher("100:1").setVpnTargets(vpnTargets)
+                .setApplyLabel(new ApplyLabelBuilder().setApplyLabelMode(
+                        new PerRouteBuilder().setApplyLabelPerRoute(true).build()).build()).build();
+
+        VpnInstanceBuilder builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey("Vpn1")).setIpv4Family
+                (ipv4Family);
         VpnInstance instance = builder.build();
         VpnManager vpnManager = new VpnManager(dataBroker, bgpManager);
         event.created.put(createVpnId("Vpn1"), instance);